# Public Tenders Scraper (`khadinakbar/scrape-public-tenders`) Actor

Search public procurement notices from EU TED and UK Contracts Finder / Find a Tender. Use for bid monitoring and govcon BD. Not SAM.gov (use sam-gov-scraper). One row per notice: title, buyer, CPV, deadline, value, URL. $0.005/notice + $0.00005 start.

- **URL**: https://apify.com/khadinakbar/scrape-public-tenders.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Lead generation, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 public tender notices

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

Search published public procurement notices from TED (EU), UK Contracts Finder, and UK Find a Tender. Each run **returns one JSON row per notice** with title, buyer, CPV codes, publication and deadline dates, value when published, and the official `sourceUrl`. HTTP-only official Search APIs, no login and no API key. Designed for govcon BD, bid monitoring, public-sector sales, and AI agents.

### Best fit for this Actor

- You want open EU or UK tenders for a keyword such as software or catering, optionally filtered by CPV and buyer country.
- You need a unified notice schema across TED and the two UK registers, with official URLs preserved.
- Start with this Actor for EU and UK notices, then use [SAM.gov Scraper](https://apify.com/khadinakbar/sam-gov-scraper) when the opportunity is a US federal notice identifier rather than a TED publication number.

### Use case: software tenders in the last week

A public-sector sales lead wants current software opportunities. They run keyword `software`, sources TED + UK Contracts Finder, `datePreset` last\_7\_days, and `maxResults` 5. Rows come back with `buyerName`, `deadlineDate`, `cpvCodes`, and `sourceUrl`. They open the official notice and decide whether to bid. An unmatched keyword in the same window finishes `VALID_EMPTY` with zero `tender-found` charges.

### Quick start input

```json
{
    "keyword": "software",
    "sources": ["ted", "uk-contracts-finder"],
    "datePreset": "last_7_days",
    "statusFilter": "open",
    "maxResults": 5
}
```

`maxResults` is the billed-row ceiling. Each saved notice is one $0.005 `tender-found` event plus the $0.00005 start event and caller-paid platform usage.

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `keyword` | string | Title/description query, e.g. `software`. Empty browses the date window. |
| `sources` | array | `ted`, `uk-contracts-finder`, `uk-find-a-tender`. Default all three. |
| `countries` | array | TED ISO3 buyer countries such as `DEU`. Ignored by UK sources. |
| `cpvCodes` | array | 2-8 digit CPV codes. TED prefix-matches. |
| `statusFilter` | enum | `open` (default), `awarded`, or `all`. |
| `datePreset` | enum | `last_24_hours`, `last_7_days`, `last_30_days`, `custom`. |
| `publishedFrom` / `publishedTo` | string | YYYY-MM-DD, used only with `custom`. |
| `expertQuery` | string | TED expert-search override. UK sources ignore it. |
| `maxResults` | integer | Run-wide billed cap, 1-250. Default 25. Prefill 5. |
| `language` | string | TED localized fields, default `ENG`. |

Unknown sources finish `INVALID_INPUT` with zero rows and zero `tender-found` charges.

### What data you receive

One dataset item is one public notice. You can download the dataset in JSON, HTML, CSV, or Excel.

```json
{
    "source": "ted",
    "tenderId": "599753-2026",
    "title": "Software licences",
    "buyerName": "Example contracting authority",
    "buyerCountry": "DEU",
    "cpvCodes": ["72000000"],
    "publicationDate": "2026-09-10",
    "deadlineDate": "2026-09-30",
    "sourceUrl": "https://ted.europa.eu/en/notice/-/detail/599753-2026",
    "scrapedAt": "2026-09-17T12:00:00.000Z"
}
```

| Field | Meaning |
|---|---|
| `source` | `ted`, `uk-contracts-finder`, or `uk-find-a-tender` |
| `tenderId` | TED publication number or UK notice id |
| `sourceUrl` | Official HTML notice |
| `estimatedValue` / `currency` | Published value when the register exposes it |

### Use through the API

```bash
curl "https://api.apify.com/v2/acts/khadinakbar~scrape-public-tenders/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"software","sources":["ted"],"maxResults":5}'
```

Read dataset items from `defaultDatasetId` after the Actor succeeds. Inspect `OUTPUT` for `outcome` (`COMPLETE`, `PARTIAL`, `VALID_EMPTY`, `INVALID_INPUT`, `UPSTREAM_FAILED`).

### Use with AI agents through Apify MCP

> Search public tenders for software in the last 7 days on EU TED and UK Contracts Finder. Return at most 5 notices with title, buyer, deadline, CPV, and source URL. Keep the search on TED and UK registers.

Inspect the terminal outcome, keep `sourceUrl` as provenance, and respect `maxResults` as the cost cap. Setup: https://mcp.apify.com

### Connect the workflow

- Start with this Actor for EU and UK notices, then use [SAM.gov Scraper](https://apify.com/khadinakbar/sam-gov-scraper) when the opportunity is a US federal notice identifier rather than a TED publication number.
- Pair it with [Clutch Scraper](https://apify.com/khadinakbar/clutch-scraper) when you already have a vendor name from a notice and want agency research next.

### Pricing

This Actor uses Pay per event plus Apify platform usage. Open the live Pricing tab for current event details.

- `apify-actor-start`: $0.00005 per run
- `tender-found`: $0.005 per persisted notice
- Empty `VALID_EMPTY` and `INVALID_INPUT` runs charge the start event only

A bounded 5-notice run costs **$0.025** in `tender-found` events ($0.005 × 5) plus **$0.00005** start, plus caller-paid platform usage shown on the Pricing tab. A 25-notice default costs $0.125 in notice events.

### Best results

- Prefer `open` + `last_7_days` for live bid pipelines; use `awarded` when you need winners.
- Provide TED `countries` as ISO3 (`DEU`).
- Bound `maxResults` first so a broad keyword stays inside the billed cap.

### Builder's note

In my testing I found TED Search returns multilingual maps such as `buyer-name: { ron: ["..."] }`. I designed the Actor to pick `ENG` then the first available translation rather than dumping every language into the row, which keeps MCP payloads under the per-item token budget.

### Responsible use

These are published government procurement notices under EU re-use and UK Open Government Licence terms. Use them for legitimate business development on public registers.

TED, Contracts Finder, Find a Tender, and SAM.gov are trademarks or public services of their respective operators. This independent Actor is not affiliated with, associated with, or endorsed by the Publications Office of the EU, Crown Commercial Service, or the U.S. General Services Administration.

### FAQ

**Where should US federal opportunities go?** Continue with [SAM.gov Scraper](https://apify.com/khadinakbar/sam-gov-scraper) when the identifier is a US federal notice rather than a TED publication number.

**How should I read VALID\_EMPTY?** The official APIs returned zero notices for that keyword/date/status combination. Widen `datePreset` to `last_30_days`, drop `countries`/`cpvCodes`, or try keyword `software` on `ted` only.

**How should I recover an UPSTREAM\_FAILED TED query?** Confirm the expert-query syntax in the run log, then rerun with a working expression from the TED expert-search page or with `expertQuery` left empty.

**Is this legal?** The Actor calls documented public APIs. You remain responsible for your use of the data and applicable procurement and privacy laws.

# Actor input Schema

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

Free-text query matched against notice titles and descriptions, for example 'software' or 'school catering'. TED uses expert FT~ search; UK Contracts Finder uses its keyword index. Leave empty to browse the date window only. This is not a CPV code — put codes in cpvCodes.

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

Which official registers to query. ted is EU Tenders Electronic Daily. uk-contracts-finder is below-threshold UK notices. uk-find-a-tender is above-threshold UK notices. Default all three. This is not SAM.gov — use sam-gov-scraper for US federal RFPs.

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

ISO 3166-1 alpha-3 buyer countries for TED only, for example DEU or FRA. Leave empty for all TED countries. UK sources always stay GBR. Do not pass two-letter codes such as DE.

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

Common Procurement Vocabulary codes, 2-8 digits, for example 72000000 for IT services. TED prefix-matches so 72 also covers 72000000 children. Leave empty for every sector. This is not a keyword.

## `statusFilter` (type: `string`):

Which procurement stage to keep. open (default) is active TED notices and Open UK Contracts Finder tenders. awarded is TED contract-award notices and Awarded UK rows. all includes planning. This is not a bid-win probability.

## `datePreset` (type: `string`):

Publication-date window applied to TED, Contracts Finder, and Find a Tender. last\_7\_days is the default quality sample. Choose custom only when publishedFrom is set. This is publication date, not bid deadline.

## `publishedFrom` (type: `string`):

Inclusive publication start date as YYYY-MM-DD, for example 2026-09-01. Used only when datePreset is custom. Ignored for last\_7\_days and other presets.

## `publishedTo` (type: `string`):

Inclusive publication end date as YYYY-MM-DD, for example 2026-09-17. Used only when datePreset is custom. Defaults to today when omitted.

## `expertQuery` (type: `string`):

Native TED expert-search expression, for example buyer-country=DEU AND classification-cpv=72000000\*. When set, it replaces the TED keyword/country/CPV/date query. Leave empty for normal use. UK sources ignore this field.

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

Hard cap on billed dataset rows for the whole run. Default 25. Prefill 5 keeps the quality sample cheap: each saved notice is one $0.005 tender-found event. This is not a page number.

## `language` (type: `string`):

TED language code for localized title and buyer fields, default ENG. Falls back to English then the first available translation. UK notices stay English. This is not a country filter.

## Actor input object example

```json
{
  "keyword": "software",
  "sources": [
    "ted",
    "uk-contracts-finder"
  ],
  "countries": [],
  "cpvCodes": [],
  "statusFilter": "open",
  "datePreset": "last_7_days",
  "publishedFrom": "2026-09-01",
  "publishedTo": "2026-09-17",
  "maxResults": 5,
  "language": "ENG"
}
```

# Actor output Schema

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

Dataset items containing source, tender id, title, buyer, CPV, dates, value, and official notice URL.

## `summary` (type: `string`):

Run summary including outcome, itemsPushed, per-source results, warnings, and billing counters.

## `runSummary` (type: `string`):

Machine-readable RUN\_SUMMARY record mirroring OUTPUT for integrations that read RUN\_SUMMARY directly.

# 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 = {
    "keyword": "software",
    "sources": [
        "ted",
        "uk-contracts-finder"
    ],
    "countries": [],
    "cpvCodes": [],
    "statusFilter": "open",
    "datePreset": "last_7_days",
    "maxResults": 5,
    "language": "ENG"
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/scrape-public-tenders").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 = {
    "keyword": "software",
    "sources": [
        "ted",
        "uk-contracts-finder",
    ],
    "countries": [],
    "cpvCodes": [],
    "statusFilter": "open",
    "datePreset": "last_7_days",
    "maxResults": 5,
    "language": "ENG",
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/scrape-public-tenders").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 '{
  "keyword": "software",
  "sources": [
    "ted",
    "uk-contracts-finder"
  ],
  "countries": [],
  "cpvCodes": [],
  "statusFilter": "open",
  "datePreset": "last_7_days",
  "maxResults": 5,
  "language": "ENG"
}' |
apify call khadinakbar/scrape-public-tenders --silent --output-dataset

```

## MCP server setup

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

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/ByVZasVU6zOzCqXG5/builds/N1ZS2h6cr4t6W8jeP/openapi.json
