# Public Tenders Scraper: UK, EU TED, Australia & US Procurement (`latamdatatools/global-public-tenders-monitor`) Actor

Government tenders and contract awards from UK Find a Tender + Contracts Finder, EU TED, AusTender and US Grants.gov / SAM.gov in one clean schema. Filter by keyword, CPV/UNSPSC/NAICS, amount, country and status. Only-new mode for daily alerts. Official open APIs only.

- **URL**: https://apify.com/latamdatatools/global-public-tenders-monitor.md
- **Developed by:** [Julian Genuario](https://apify.com/latamdatatools) (community)
- **Categories:** Lead generation, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 tender notices

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/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

## Public Tenders Scraper: UK, EU TED, Australia & US Procurement

Get **government tenders and contract awards from several countries in one clean, normalized dataset**: UK Find a Tender Service, UK Contracts Finder, EU TED (Tenders Electronic Daily, all EU/EEA countries), AusTender (Australia) and the US (Grants.gov, plus SAM.gov with your own free key).

Filter by **keywords, CPV / UNSPSC / NAICS codes, country, amount and status** (open or awarded), and switch on **"only new notices"** to get a daily alert with just what was published since the last run.

The Actor only uses **official open-data APIs** published by each government (no logins, no scraping of web pages, no proxies).

### What does Public Tenders Scraper do?

Public Tenders Scraper collects government tenders, RFPs and contract award notices from official procurement APIs (EU TED, UK Find a Tender and Contracts Finder, AusTender, US Grants.gov and SAM.gov) in one clean schema. Filter by keyword, CPV / UNSPSC / NAICS code, amount, country and status, and use only-new mode for daily tender alerts.

### Who is it for?

- **B2G suppliers and SMEs** that sell to governments in more than one country and are tired of checking five portals every morning.
- **Bid consultants and tender agencies** that monitor opportunities for many clients (one saved search per client with "Alert name").
- **Market intelligence and sales teams**: who won which contract, for how much, and which buyers are spending in your category (status "Awarded").
- **Researchers and journalists** analysing public procurement across countries with one schema.

### What you get (one row per notice)

| Field | Example |
|---|---|
| `source`, `sourceName`, `country` | `eu-ted`, "EU TED", `ES` |
| `noticeId`, `referenceNumber`, `ocid` | `733607-2026` |
| `title`, `titleOriginal`, `description` | English title (TED) + original-language title |
| `buyerName`, `buyerCountry`, `buyerLocation` | "Universidad del País Vasco", `ES`, "Leioa" |
| `category`, `noticeType`, `procedureType` | `services`, `cn-standard`, `open` |
| `classifications`, `mainClassification` | CPV / UNSPSC / NAICS / PSC codes with scheme |
| `amount`, `currency`, `amountKind` | `318240`, `EUR`, `estimated` / `awarded` / `award ceiling` |
| `amountUsd`, `amountEur` | converted with the day's ECB reference rates |
| `publishedAt`, `closingAt` | ISO 8601 dates (closing = deadline for bids) |
| `status` | `open`, `closed`, `planned`, `awarded`, `cancelled` |
| `awardedTo`, `awardDate` | winners of awarded contracts |
| `url`, `apiUrl` | official notice page and official machine-readable record |
| `matchedKeywords`, `isNew`, `fetchedAt` | which of your keywords matched |

Every row has the same keys (null when a source does not publish that field), so it drops straight into Google Sheets, Excel, a CRM or a database. A `RUN_SUMMARY` record in the key-value store shows per-source counts, warnings and errors.

### Sources

| Source | Country | What it contains | Notes |
|---|---|---|---|
| `uk-fts` | United Kingdom | Find a Tender Service: higher-value UK public procurement (planning, tenders, awards) | OCDS API, Open Government Licence |
| `uk-contracts-finder` | United Kingdom (England) | Contracts Finder: lower-value contracts (from ~£12k / £30k) | OCDS API, Open Government Licence |
| `eu-ted` | EU / EEA | TED: all above-threshold notices of the 27 EU countries and more | TED API v3 anonymous search; keyword search runs on the full text in every language |
| `au-austender` | Australia | AusTender **contract notices** (awarded contracts, with supplier and value) | OCDS API, CC BY. The open API does not include open tenders, so Australia only returns results with status "Awarded" or "All" |
| `us-grants` | United States | Grants.gov federal funding opportunities (grants and cooperative agreements) | Public API, no key. Grants, not procurement contracts |
| `us-sam` | United States | SAM.gov contract opportunities (solicitations, presolicitations, awards) | **Needs your own free SAM.gov API key** (see below) |

UK notices that appear on both Find a Tender and Contracts Finder are de-duplicated (same title + buyer).

### How to use it

#### Daily tender alert (most common)

1. Choose sources, add keywords (and CPV codes if you know them), status **Open tenders**.
2. Turn on **Only new notices since the last run** and give the alert a name.
3. Create an **Apify Schedule** (e.g. every weekday at 08:00) and add an integration: email, Slack, Google Sheets, Make, Zapier or a webhook.
   Each run returns only notices that were not delivered before, so you only pay for new ones.

#### Example input

```json
{
  "sources": ["uk-fts", "uk-contracts-finder", "eu-ted", "us-grants"],
  "keywords": ["cyber security", "cybersecurity", "penetration test"],
  "status": "open",
  "daysBack": 2,
  "cpvCodes": ["72000000"],
  "minAmount": 50000,
  "amountCurrency": "EUR",
  "onlyNew": true,
  "stateKey": "cyber-alert"
}
```

#### Market research on awarded contracts

Status **Awarded contracts**, a date range of up to 92 days, add `au-austender`, and filter by UNSPSC / CPV codes to see winners and contract values.

### Filters in detail

- **Keywords**: a notice is kept if any keyword appears in its title, description, buyer or category names (case and accent insensitive). On TED, the official full-text search pre-selects notices and the same title/description check is applied, so boilerplate matches are dropped. TED titles come in English, but descriptions stay in the original language: add translations for non-English countries (`software`, `logiciel`, `Softwareentwicklung`…) or use CPV codes.
- **Codes**: matched as prefixes, so `72000000` (IT services) also matches `72212000`. CPV applies to UK + TED, UNSPSC to AusTender, NAICS to SAM.gov. A source is only filtered by the codes of its own scheme.
- **Amount**: estimated value for open tenders, awarded value for awards (Grants.gov: award ceiling). Converted with ECB reference rates. Many notices publish no amount: keep or drop them with *Keep notices without a published amount*.
- **Status**: `open` (closing date not passed), `open-and-planned` (adds prior information / forecast notices), `awarded`, `all`.
- **Dates**: last N days (`daysBack`) or `dateFrom` / `dateTo` (max 92 days per run).

### SAM.gov API key (optional)

SAM.gov only answers with a personal API key. It is free: sign in at [sam.gov](https://sam.gov) (Login.gov account), open **Account Details**, and request a **Public API Key**. Paste it in *Your SAM.gov API key* (stored as a secret input). Non-federal keys have a small daily request quota, so the Actor asks for 1,000 results per request and does not download descriptions. Without a key, SAM.gov is skipped with a warning and the other sources still run.

### Pricing

Pay per event: **USD 5 per 1,000 notices** in the results (USD 0.005 per notice) plus a small start fee per run. Notices filtered out, duplicates and, with "only new", notices you already received are **not charged**. The Actor respects your "maximum charge per run".

### Limits and good practice

- Requests are spaced out per API (1-2.5 s), with automatic retries and back-off on rate limits (HTTP 429) and server errors. Some UK runs wait up to a minute when the UK service asks to slow down.
- Wide searches without keywords can return thousands of notices per day; use *Max notices*, *Max notices per source* and *Max API pages per source*.
- If one source is down, the others are still saved and the problem is listed in `RUN_SUMMARY`.
- Data belongs to the publishing governments and is used under their open licences (UK Open Government Licence v3.0, EU TED reuse policy, AusTender CC BY, US public domain). Check each licence before redistributing.

### Why use Public Tenders Scraper

- **Six official sources in one schema:** EU TED, UK Find a Tender, UK Contracts Finder, AusTender, US Grants.gov and (with your free key) SAM.gov.
- **Comparable amounts:** each notice carries its original amount plus `amountUsd` and `amountEur` (ECB rates).
- **Daily alerts without duplicates:** `onlyNew` remembers what you already received, per alert name, and does not charge for it again.
- **Real filters:** keywords, CPV (UK and EU), UNSPSC (Australia), NAICS (SAM.gov), EU countries, status and amount range. Filtered-out notices are not charged.
- **Official open APIs only.** No scraping of portals that forbid it.

### Cost examples

Prices at the current pay-per-event rates (see Pricing). You can set a maximum charge per run in the run options.

| Job | Approximate cost |
|---|---|
| One run with 50 notices | about $0.27 ($0.02 start + 50 x $0.005) |
| Daily alert with about 20 new notices, one month | about $3.60 |
| 1,000 awarded contracts for market research | about $5.02 |

### Use it from your code, an integration or an AI agent

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("latamdatatools/global-public-tenders-monitor").call(run_input={
    "sources": [
        "uk-fts",
        "uk-contracts-finder",
        "eu-ted"
    ],
    "keywords": [
        "software",
        "cyber security",
        "cloud"
    ],
    "status": "open",
    "daysBack": 2,
    "maxItems": 50
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript / Node.js** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('latamdatatools/global-public-tenders-monitor').call({
  "sources": [
    "uk-fts",
    "uk-contracts-finder",
    "eu-ted"
  ],
  "keywords": [
    "software",
    "cyber security",
    "cloud"
  ],
  "status": "open",
  "daysBack": 2,
  "maxItems": 50
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**No code:**

- **Schedules:** run it daily or weekly from Apify Console (Schedules), with the same input saved as a Task.
- **Integrations:** send results to Google Sheets, Slack, email, Make, Zapier, n8n or Airbyte from the Integrations tab, or call your own webhook when a run finishes.
- **AI agents:** add it as a tool in Claude, Cursor, VS Code and other MCP clients through the Apify MCP server (`https://mcp.apify.com`), so the agent can run Public Tenders Scraper and read the results.

### FAQ

**Is this the full TED / SAM.gov / Find a Tender database?** It searches the official live APIs for the dates you choose (up to 92 days per run). For long historical exports, run several date ranges.

**Can I get the tender documents?** The `url` field links to the official notice, where documents are published. Many UK and EU tenders require registering on the buyer's e-procurement portal to download documents.

**Why does Australia return nothing with status "Open"?** AusTender's open data API only publishes awarded contract notices.

**A country I need is missing?** Open an issue with the country and the official API, and it will be considered.

**How do I get new tenders by email or Slack every morning?** Turn on `onlyNew`, save the input as a Task, add a daily Schedule, and connect the Slack or email integration (or a webhook) to the run's dataset.

# Actor input Schema

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

Official open-data APIs to search. AusTender only publishes awarded contracts (use status "Awarded" or "All"). SAM.gov needs your own free API key (field below).

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

A notice is kept if ANY keyword appears in its title, description, buyer or category (case and accent insensitive). Leave empty to get everything. TED titles are in English but descriptions stay in the original language, so add translations (e.g. "software", "logiciel") or use CPV codes.

## `status` (type: `string`):

"Open" = calls for tenders still accepting bids (closing date not passed). "Awarded" = contract award notices with winners and values.

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

Notices published in the last N days (0 = today only). Ignored when "Date from" is set, and on "only new" runs after the first one.

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

Publication date from, YYYY-MM-DD. Maximum range 92 days per run.

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

Publication date to, YYYY-MM-DD. Default: today.

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

Remembers which notices were already delivered (in a named key-value store in your account) and returns only new ones. Combine with an Apify Schedule for daily email/Slack/webhook alerts. You are only charged for new notices.

## `stateKey` (type: `string`):

Use a different name for each saved search when you run several alerts with "only new".

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

Optional. Common Procurement Vocabulary codes, matched as prefixes: "72000000" (IT services) also matches 72212000. Applies to UK and TED.

## `unspscCodes` (type: `array`):

Optional. UNSPSC codes, matched as prefixes ("43000000" = IT and telecom). Applies to AusTender.

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

Optional. NAICS codes, matched as prefixes ("5415" = computer systems design). Applies to SAM.gov.

## `euCountries` (type: `array`):

Optional. Buyer countries for TED as ISO codes, e.g. DE, FR, ES, IE, NL. Empty = all.

## `minAmount` (type: `integer`):

Optional. Estimated (or awarded) value, in the currency below. Values in other currencies are converted with ECB reference rates.

## `maxAmount` (type: `integer`):

Optional.

## `amountCurrency` (type: `string`):

Currency of the minimum and maximum amount.

## `includeWithoutAmount` (type: `boolean`):

Many notices do not publish a value. When an amount filter is set, keep them (true) or drop them (false).

## `maxItems` (type: `integer`):

Stop after this many notices in total (you pay per notice in the results).

## `maxItemsPerSource` (type: `integer`):

Optional cap per source so one big source does not use the whole limit. 0 = no cap.

## `maxPagesPerSource` (type: `integer`):

Safety limit (100 notices per page) for wide searches without keywords.

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

Free public API key from your SAM.gov account (Account Details > Public API Key). Non-federal keys have a small daily request quota; the Actor uses up to 1,000 results per request to save it. See the README.

## Actor input object example

```json
{
  "sources": [
    "uk-fts",
    "uk-contracts-finder",
    "eu-ted"
  ],
  "keywords": [
    "software",
    "cyber security",
    "cloud"
  ],
  "status": "open",
  "daysBack": 2,
  "onlyNew": false,
  "stateKey": "default",
  "amountCurrency": "USD",
  "includeWithoutAmount": true,
  "maxItems": 50,
  "maxItemsPerSource": 0,
  "maxPagesPerSource": 50
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runSummary` (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 = {
    "sources": [
        "uk-fts",
        "uk-contracts-finder",
        "eu-ted"
    ],
    "keywords": [
        "software",
        "cyber security",
        "cloud"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("latamdatatools/global-public-tenders-monitor").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 = {
    "sources": [
        "uk-fts",
        "uk-contracts-finder",
        "eu-ted",
    ],
    "keywords": [
        "software",
        "cyber security",
        "cloud",
    ],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("latamdatatools/global-public-tenders-monitor").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 '{
  "sources": [
    "uk-fts",
    "uk-contracts-finder",
    "eu-ted"
  ],
  "keywords": [
    "software",
    "cyber security",
    "cloud"
  ],
  "maxItems": 50
}' |
apify call latamdatatools/global-public-tenders-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,latamdatatools/global-public-tenders-monitor"
        }
    }
}
```

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/adjsXiAXtQkvhXF2o/builds/l3QKm0K01ABPhzBja/openapi.json
