# Government Tenders Scraper: SAM.gov, TED EU, UK & Canada (`tidytools/government-tenders-scraper`) Actor

Public tenders and contract awards from 5 official sources in one format: SAM.gov, EU TED, UK Find a Tender, Contracts Finder, CanadaBuys. Keywords, CPV/NAICS, countries, value, open deadlines; only-new alerts; CSV. $3 per 1,000 notices.

- **URL**: https://apify.com/tidytools/government-tenders-scraper.md
- **Developed by:** [Yukai Lin](https://apify.com/tidytools) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 notices

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

### What does Government Tenders Scraper do?

**Enter keywords, countries or CPV / NAICS codes (all optional), get one row per tender or contract award from SAM.gov, TED, UK Find a Tender, Contracts Finder and CanadaBuys, with title, buyer, deadline, value, codes, link and the buyer's published contact point, at $3 per 1,000 notices.** Notices dropped by your filters, closed tenders, notices seen in earlier runs and sources that cannot be read are free. No start fee.

It collects **public tenders and contract awards** from five official government sources and returns them in **one format**, so one search, one schedule and one spreadsheet cover the US, the EU, the UK and Canada:

| Source | Coverage | Read through |
|---|---|---|
| **SAM.gov** | US federal contract opportunities: solicitations, presolicitations, sources sought, award notices | the official Contract Opportunities data extract (updated daily) |
| **TED** | EU and EEA tenders above the EU thresholds: contract notices, prior information, contract awards | the official TED Search API v3 |
| **Find a Tender** | UK public tenders (all notices under the Procurement Act 2023) | the official OCDS API |
| **Contracts Finder** | UK (England) lower-value tenders and awards | the official OCDS API |
| **CanadaBuys** | Canadian federal open tender notices | the official open-data file |

- 🔎 **Filters**: keywords (full text, TED in every EU language), buyer countries, **CPV codes** (EU/UK), **NAICS codes** (US), minimum value, exclude words, open tenders only.
- 🗂️ **One schema**: title, buyer, country, city, published date, **deadline and days left**, estimated value and currency, CPV/NAICS/UNSPSC, category in English, contract type (goods/services/works), procedure, US set-aside, SME suitability, winners and award value, notice link and where to respond.
- 🏆 **Contract awards**: who won, for how much, when (SAM.gov, TED, both UK sources).
- 🔔 **Only new** for daily bid alerts: each notice is returned once; notices seen before are skipped for free.
- 📄 **CSV file** with the main columns.

#### Why this Actor?

- **Five official sources in one run**: most Store Actors cover one or two portals (SAM.gov, TED or one UK site). Here a single schedule watches all five, newest first; within a publication day the sources take turns, so a small "Max notices" is not filled by the busiest source alone (SAM.gov's daily file is always one day behind TED, so TED days come first).
- **Official APIs and files only**: no login, no key, no browser, no scraping of search pages. Requests name our tool and contact address, and the UK platform's rate limit is respected.
- **$3 per 1,000 notices**, and you pay only for what you keep: filtered notices, closed tenders, notices seen before and failed sources are free.

#### Real results (4 October 2026, local runs)

- Default input ("software", last 3 days, max 100): **all five sources read in 11 seconds**, 220 matching notices, the 100 newest returned for $0.30 (91 TED, 5 SAM.gov, 2 Find a Tender, 2 CanadaBuys).
- Everything (all notice types, 3 days, no filters): **10,426 notices** in 86 seconds (TED 7,256, SAM.gov 1,900, Find a Tender 955, Contracts Finder 256, CanadaBuys 59).
- IT tenders in Germany, France and the Netherlands (CPV 72 + 48, value ≥ 100,000, 7 days): 208 notices in 11 seconds, $0.62. Example: GIE SESAM-Vitale (FR), IT security assistance, €2.7 million, deadline 2 November.
- US computer-services opportunities (NAICS 5415, tenders + early notices, 7 days): 47 notices in 5 seconds; 15.8 MB of the SAM.gov file read.
- UK software contract awards (7 days): 200 awards in 5 minutes (the UK platform allows about 12 requests a minute), e.g. "Cyber SOC Service", Department for Culture, Media and Sport → Sapphire Technologies Ltd, £920,000.
- The default input again with "Only new": the 100 notices of the first run were skipped (free), the next 100 were returned.

### Use cases

- **Bid alerts for suppliers**: IT, consulting, construction, cleaning, medical or defence suppliers get every new opportunity in their codes and countries each morning.
- **Bid/tender teams and consultants**: one feed for US federal, EU and UK work instead of five portals.
- **Market and competitor research**: contract awards by buyer, supplier and value; who wins what in your sector.
- **Lead generation**: winners of public contracts are companies with fresh budgets and projects.
- **Data products and AI agents**: a normalised tender dataset with codes and links, ready for a database or an LLM.

### How to use it

1. **Keywords** (optional): words or phrases, any of them must appear.
2. **Sources**: keep all five or pick some.
3. **Notices**: open tenders (default), tenders + early notices, contract awards, or all.
4. **Published in the last N days** (1-90).
5. Optional: **buyer countries** (DE, FR, GB, US, CA ...), **CPV codes** (EU/UK), **NAICS codes** (US), **minimum value**, **exclude keywords**.
6. For a daily alert: turn on **Only new notices**, give a **Monitor name**, and schedule the task every day with "last 3 days" (Apify Console → Schedules).

#### Input example

```json
{
    "keywords": ["software", "cloud", "cyber"],
    "sources": ["sam", "ted", "uk-fts", "uk-cf", "canadabuys"],
    "noticeTypes": "tenders",
    "daysBack": 3,
    "cpvCodes": ["72", "48"],
    "naicsCodes": ["5415"],
    "minValue": 50000,
    "maxResults": 500,
    "onlyNew": true,
    "monitorName": "it-tenders-daily"
}
```

With a code filter, each source is matched by its own scheme (CPV for TED and the UK, NAICS for SAM.gov); sources whose scheme has no filter are skipped, which is why the example sets both. CanadaBuys has neither scheme and is skipped when codes are set.

#### Output example

A real TED notice from 2 October 2026 (shortened; contact values as published in the notice):

```json
{
    "type": "notice",
    "source": "ted",
    "sourceName": "TED (EU and EEA)",
    "noticeId": "678030-2026",
    "noticeType": "cn-standard",
    "stage": "tender",
    "title": "Assistance technique sécurité",
    "category": "IT services: consulting, software development, Internet and support",
    "language": "fra",
    "description": "Le marché porte sur la réalisation de prestations d'assistance technique dans le domaine de la sécurité des systèmes d'information ...",
    "buyerName": "GIE SESAM-Vitale",
    "buyerCountry": "FR",
    "buyerCity": "Le mans cedex 2",
    "publishedDate": "2026-10-02",
    "deadline": "2026-11-02T12:00:00+02:00",
    "daysToDeadline": 29,
    "cpvCodes": ["72000000"],
    "contractType": "services",
    "procedure": "neg-w-call",
    "estimatedValue": 2700000,
    "currency": "EUR",
    "url": "https://ted.europa.eu/en/notice/-/detail/678030-2026",
    "submissionUrl": "http://www.achatpublic.com",
    "contactEmail": "(buyer's published contact)",
    "charged": true
}
```

#### What the fields mean

- **stage**: `tender` (open for bids), `planning` (prior information, presolicitation, sources sought), `award` (contract awarded), `other` (modifications, cancellations, special notices). **noticeType** is the source's own type (e.g. `cn-standard`, `UK4`, `Solicitation`).
- **title** is in the notice's language (**language**: ISO 639-3 for TED); **category** is the main CPV or UNSPSC category in English, so non-English notices stay readable.
- **deadline**: tender deadline as published, with time zone when the source gives one (for restricted EU procedures, the deadline for requests to participate). **daysToDeadline**: full days left at run time.
- **estimatedValue** (tenders) and **awardValue** (awards) are in **currency**, as stated in the notice; many notices state no value.
- **cpvCodes** (TED, UK), **naicsCode** and **pscCode** (SAM.gov), **unspscCodes** (CanadaBuys); **setAside** (US small-business set-aside), **smeSuitable** (UK).
- **awardedSuppliers**, **awardDate**: winners of award notices.
- **url**: the official notice page; **submissionUrl**: the buyer's e-tendering portal when the notice gives one.
- **contactName / contactEmail / contactPhone**: the buyer's contact point for this procurement (off with **Buyer contact**).
- **SUMMARY** (key-value store): notices per source, notices read, filtered out per filter, sources skipped and why, SAM.gov and CanadaBuys file dates, failures, cost plan.

### How much does it cost?

| Event | Price | When |
|---|---|---|
| Notice | **$3.00 / 1,000** ($0.003 each) | one tender, early notice or contract award returned after your filters |

**Free:** notices dropped by your filters or keywords, tenders whose deadline has passed, notices seen in earlier runs ("Only new"), sources that cannot be read. **No start fee.** Larger Apify plans get the usual volume discount (Silver 10%, Gold and above 20%).

**Example (our test week):** IT tenders (CPV 72/48, value ≥ 100,000) in Germany, France and the Netherlands came to about 40 per business day, so a daily alert costs about $0.12 a day; US NAICS 5415 tenders and early notices about 7 per day ($0.02).

For comparison (Apify Store, 4 October 2026, price per result): SAM.gov: scrapesage/sam-gov-scraper $0.002, fortuitous_pirate/sam-gov-scraper $0.003, taroyamada/procurement-intel-actor (TED + SAM.gov) $0.008; UK: ciel_labs/uk-government-tenders-contracts-finder $0.008, neverempty/uk-tenders-scraper $0.01, publicmoney/find-a-tender-scraper $0.002; TED: foxlabs/ted-tenders $0.004, dltik/ted-europa-scraper $0.005, memo23/ted-tenders-scraper $0.001.

#### Control your cost

- **Max notices** stops the run after that many notices (newest first).
- At the start the run logs the worst case (notices × $0.003) and compares it with your **maximum charge per run**; notices that would pass it are not returned (`SUMMARY.status: LIMIT_REACHED`, `SUMMARY.notProcessed`).
- Every row has `charged: true` or `false`; free rows say "(not charged)". If Apify restarts the run, notices already returned are not charged again.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/tidytools~government-tenders-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["cybersecurity"],"daysBack":3,"countries":["GB","IE","DE"]}'
```

**With AI agents (MCP):** connect Apify's MCP server (`https://mcp.apify.com?tools=tidytools/government-tenders-scraper`) to Claude, Cursor or any MCP client and ask, for example, "Which open EU tenders for cloud hosting over €500,000 were published this week?". Minimal input: `{"keywords": ["cloud hosting"], "sources": ["ted"], "minValue": 500000, "daysBack": 7}`. Failed sources are not charged and carry an `errorType`.

### Limitations

- **SAM.gov comes from its daily extract** (published once a day around 03:30 UTC), so the newest US notices are from the previous day; `SUMMARY.sources.sam.dataAsOf` shows the file date. The extract holds the latest version of each notice.
- **UK rate limit**: Find a Tender and Contracts Finder allow about 12 requests a minute; long date ranges (a week or more) take a few minutes, and a busy platform can ask us to wait 2 minutes.
- **TED publishes Monday to Friday**; keywords are searched by TED in its full text, so a match can be in a translated part of the notice.
- **CanadaBuys open data lists open tender notices** only (no awards); notices with no notice link get the standard CanadaBuys tender-notice link.
- **Values are as published**: many notices state none, and values are not converted between currencies (minimum value compares in the notice's own currency).
- Below-threshold tenders of EU countries appear only on national portals, not on TED.

### Responsible use

- All data comes from official public-procurement publications that buyers publish so that suppliers can bid.
- The contact fields are the contact point the buying organisation published for this procurement (often a shared mailbox, sometimes the name of a procurement officer). Use them only for questions about that procurement. Turn off **Buyer contact** (`includeContacts`) for a dataset without any personal names or direct contacts; the price does not change.
- You are responsible for following data-protection and anti-spam laws (GDPR, CAN-SPAM, CASL) when you contact anyone.

### FAQ

**Does the Actor collect usage data?** The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

**What happens if my input is wrong?** The run ends normally (it does not fail) with a free row, `errorType: "invalid_input"`, and a message saying what to fix: an unknown source, a country that is not a 2-letter code, a CPV or NAICS code that is not a number prefix, or filters that no selected source can match (for example only CPV codes with SAM.gov, or awards from CanadaBuys alone). Nothing is charged.

**What if nothing matches?** You get one free row with `errorType: "no_results"` naming the filter that dropped the most notices; `SUMMARY.status` is `NO_RESULTS`. A source that cannot be read is a separate free error row and the other sources still run. In "Only new" runs with nothing new there is no extra row.

**Is this data legal to use?** Yes. Tender and award notices are public records published by the US government (SAM.gov), the EU Publications Office (TED, free reuse), the UK government (Open Government Licence) and the Government of Canada (Open Government Licence - Canada). The Actor uses their official APIs and open-data files.

**Why do I see fewer notices than the portal shows?** The default returns open tenders only, drops tenders whose deadline has passed and amendments. `SUMMARY.filteredOutBy` shows how many each filter removed; all of them are free.

**How do I get a daily email or Slack alert?** Schedule a task with "Only new notices" and "last 3 days", then add an Apify integration (email, Slack, Zapier, Make) on the task's successful runs.

**Can I search one country's tenders only?** Yes: set **Buyer countries**. Sources that cannot have buyers there are skipped automatically (e.g. only TED for DE).

**Which code system should I use?** CPV for Europe and the UK (e.g. 72 IT services, 45 construction), NAICS for the US (e.g. 5415 computer systems design, 236 building construction).

### Related Actors

- [SEC Form D Scraper](https://apify.com/tidytools/sec-form-d-scraper): US companies that just raised money.
- [Company Website Enrichment](https://apify.com/tidytools/company-website-enrichment): description, industry and social links for contract winners.
- [Email Extractor](https://apify.com/tidytools/website-contact-extractor): contact details from company websites.

# Actor input Schema

## `keywords` (type: `array`):

Keep notices that mention at least one of these words or phrases in the title, description or buyer name, e.g. "software", "cleaning services", "NHS". TED searches its full text in every EU language (an English word also finds notices whose English title matches). Empty = all notices.

## `sources` (type: `array`):

Official public-procurement sources to search. Empty = all five.

## `noticeTypes` (type: `string`):

Stage of the procurement. Awards come from SAM.gov, TED and the two UK sources (CanadaBuys open data lists open tenders only).

## `daysBack` (type: `integer`):

Notices published today and in the previous days (UTC calendar days). SAM.gov publishes its file once a day, so its newest notices are from yesterday.

## `countries` (type: `array`):

2-letter codes of the buyer's country, e.g. DE, FR, IE, GB, US, CA. Sources that cannot have such buyers are skipped. Empty = every country.

## `cpvCodes` (type: `array`):

Common Procurement Vocabulary prefixes, e.g. 72 (IT services), 48 (software packages), 45 (construction work), 79 (business services), or a full code like 72212000. Used by TED and the UK sources. With a code filter, sources without matching codes are skipped (set NAICS codes too to keep SAM.gov).

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

NAICS prefixes for US notices, e.g. 5415 (computer systems design), 541511, 236 (construction of buildings). With a code filter, sources without matching codes are skipped (set CPV codes too to keep TED and the UK).

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

Drop notices whose title contains one of these words, e.g. "framework", "vehicle". Dropped notices are free.

## `minValue` (type: `integer`):

Drop notices whose stated estimated value (or award value) is below this amount, in the notice's own currency (EUR, GBP, USD ...). Notices without a stated value are kept.

## `onlyOpen` (type: `boolean`):

Drop tenders whose response deadline has already passed (free). Tenders without a stated deadline are kept.

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

Stop after this many notices (newest first across all sources). In our test week a business day had about 1,900 open tenders on TED, 200-700 SAM.gov solicitations, 110-150 UK tenders and 30 CanadaBuys tenders; with all notice types about 3,600 (TED) and 1,000 (SAM.gov).

## `includeContacts` (type: `boolean`):

The contact point the buying organisation published in the notice for bidder questions (email, phone and, when given, the name of the procurement contact). Turn off for a dataset without any personal names or direct contacts (same price).

## `descriptionChars` (type: `integer`):

Longest description kept per notice, in characters (longer ones end with "…"). 0 = no description.

## `includeUpdates` (type: `boolean`):

Also return amended or updated versions of notices (UK tender updates, SAM.gov modifications, CanadaBuys amendments, TED change notices) as separate rows. Off = original notices only.

## `csvExport` (type: `boolean`):

Also save TENDERS.csv (one row per notice, the main columns) in the run's key-value store, ready for Sheets, Excel or a CRM import. Free.

## `onlyNew` (type: `boolean`):

Skip notices returned by earlier runs of the same monitor (free), so a daily schedule with "last 3 days" returns each notice once. Notices are remembered for 180 days.

## `monitorName` (type: `string`):

Name of the saved state (letters, digits, dashes). Use one name per schedule and a new one when you change the filters; empty = derived from the filters.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "sources": [
    "sam",
    "ted",
    "uk-fts",
    "uk-cf",
    "canadabuys"
  ],
  "noticeTypes": "tenders",
  "daysBack": 3,
  "onlyOpen": true,
  "maxResults": 100,
  "includeContacts": true,
  "descriptionChars": 3000,
  "includeUpdates": false,
  "csvExport": true,
  "onlyNew": false,
  "monitorName": ""
}
```

# Actor output Schema

## `tenders` (type: `string`):

No description

## `awards` (type: `string`):

No description

## `bidding` (type: `string`):

No description

## `full` (type: `string`):

No description

## `errors` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `summary` (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 = {
    "keywords": [
        "software"
    ],
    "daysBack": 3,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidytools/government-tenders-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 = {
    "keywords": ["software"],
    "daysBack": 3,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("tidytools/government-tenders-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 '{
  "keywords": [
    "software"
  ],
  "daysBack": 3,
  "maxResults": 100
}' |
apify call tidytools/government-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tidytools/government-tenders-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/MCtFa3ieS768GEaSh/builds/X4N7lfgVWgjDU8lRY/openapi.json
