# Kuwait Government Tenders (CAPT) Scraper (`automatic/kuwait-capt-tenders-scraper`) Actor

Kuwait government tenders from CAPT: tender number, subject, buying entity, publish and closing dates, fees, bond and meeting details, plus awarded contracts with the winning bidder and value. Filter by keyword, entity, status or dates for daily alerts.

- **URL**: https://apify.com/automatic/kuwait-capt-tenders-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/automatic) (community)
- **Categories:** Lead generation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 tenders

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

## Kuwait CAPT Tenders Scraper

Kuwait government tenders from the Central Agency for Public Tenders (CAPT, capt.gov.kw), the body that runs public procurement for Kuwaiti ministries and public authorities. One row per tender: tender number, subject, purchasing entity, publication and closing dates, document price, initial bond, the pre-bid meeting, the required classification — and, for awarded contracts, the winning bidder and the awarded amount.

Use it for tender monitoring and alerts: schedule a daily run with a buying entity, keyword or date window and send the new tenders to email, Slack or a spreadsheet.

### Use cases

- Watch Kuwaiti government tenders by entity, keyword or closing date.
- Build a daily feed of open tenders before their offer deadline.
- Track what CAPT has awarded, to whom and for how much.
- Match tenders against your classification: the required type and category come with each open tender.
- Prepare for the pre-bid meeting: its date and place are included.

### What it returns

Every row has `tenderId`, `tenderNumber`, `title`, `buyer`, `procurementMethod`, `status`, `publishedAt`, `deadlineAt`, `awardedAt`, `winner`, `awardValue`, `currency`, `tenderFee`, `initialBond`, `classificationTypes`, `alternativeOffers`, `divisible`, `notes`, `initialMeetingAt`, `initialMeetingLocation`, `url`, `changeType`, `changedFields`, `detailIssue`, `sourceQuery`, `source`, `country`, `scrapedAt` and a few reserved fields (`titleEnglish`, `category`, `estimatedValue`, `documents`) that stay null, explained below.

- `status` is `open` for tenders still accepting offers and `awarded` for awarded contracts.
- `title` is the subject exactly as published, usually in Arabic.
- Dates are ISO 8601 (`YYYY-MM-DD`). CAPT prints dates without a time, so no time is invented.
- `tenderFee` is the document purchase price in KWD; `initialBond` is the initial insurance in KWD. Neither is a contract estimate, so `estimatedValue` stays null.
- `classificationTypes` lists the required classification rows (`type` and `category`) from the tender's classification panel, when details are on.
- `awardValue` is the awarded amount in KWD. When CAPT prints a discount instead of a total, `awardValue` is null and `awardValueText` carries the printed percentage.
- `documents` stays null: CAPT serves tender documents only to signed-in companies. The `url` is the CAPT listing page that shows the tender.
- If one tender's extra panels cannot be read, the row is still delivered with `detailIssue` explaining what was missing.
- When CAPT awards a tender item by item, `winner` lists each winning bidder (separated by `; `), `awardValueText` gives each item's printed price, and `awardValue` is their KWD total when every item has one. These come from the tender's items panel, read when `includeDetails` is on.
- Rows are deduplicated on tender number and buying entity: CAPT reuses the same number for different entities' tenders.

### Input

| Field | Type | Default | What it does |
|---|---|---:|---|
| `keyword` | string | `""` | Text matched in the tender subject or notes, e.g. `صيانة`. |
| `buyer` | string | `""` | Part of the purchasing entity name, e.g. `Ministry of Health`. |
| `status` | string | `open` | `open` tenders or `awarded` contracts. |
| `publishedFrom`, `publishedTo` | string | `""` | Publication window, `YYYY-MM-DD`. For awarded rows, the award date. |
| `closingFrom`, `closingTo` | string | `""` | Offer deadline window, `YYYY-MM-DD`. Open tenders only. |
| `maxItems` | integer | `20` | Maximum tenders returned. |
| `includeDetails` | boolean | `true` | Read each open tender's meeting and classification panels, and the winners of tenders awarded by item. Slower. |
| `onlyNewSinceLastRun` | boolean | `false` | Deliver only tenders that are new or changed since the last run. |
| `stateKey` | string | `""` | Optional name for this search's ledger. Defaults to a key derived from the filters. |

All filters are optional and can be combined. An empty input returns the latest open tenders.

### Example queries

Open tenders for the Ministry of Health closing this month:

```json
{
  "buyer": "Ministry of Health",
  "closingFrom": "2026-11-10",
  "closingTo": "2026-11-30",
  "maxItems": 50
}
```

A daily feed of new maintenance tenders:

```json
{
  "keyword": "صيانة",
  "onlyNewSinceLastRun": true,
  "stateKey": "maintenance-daily"
}
```

Recent awards to one entity:

```json
{
  "status": "awarded",
  "buyer": "Ministry of Electricity",
  "maxItems": 30
}
```

### Use it as a daily feed

Set `onlyNewSinceLastRun` and run the Actor on a schedule. The first run delivers
every tender that matches your filters. Later runs deliver only tenders that are
new, or whose deadline, status, value, documents or award changed, with
`changeType` set to `new` or `changed` and `changedFields` naming what moved. Every
matched tender that did not change is skipped, and the run summary says how many
were skipped. Use `stateKey` to keep separate ledgers for separate searches.

### Output example

```json
{"tenderId":"6/2025/2026","tenderNumber":"6/2025/2026","title":"اصلاح وصيانه جذريه وتشغيل الخدمات الفنيه واصلاح وصيانه دوريه بسيطه في الاسواق والساحات والشواطئ في دوله الكويت","titleEnglish":null,"buyer":"Kuwait Municipality","category":null,"procurementMethod":"Limited","status":"open","publishedAt":"2026-11-08","deadlineAt":"2026-12-08","awardedAt":null,"estimatedValue":null,"currency":"KWD","documents":null,"url":"https://capt.gov.kw/en/tenders/opening-tenders/?page=1","changeType":null,"changedFields":null,"tenderFee":1000.0,"initialBond":45000.0,"classificationTypes":[{"type":"الأعمال الميكانيكية","category":"الفئة الثالثة"}],"alternativeOffers":"لا يقبل عروض بديلة","divisible":"غير قابلة للتجزئة","notes":null,"initialMeetingAt":"2026-11-15","initialMeetingLocation":"بلدية الكويت- ادارة الانشاءات","winner":null,"awardValue":null,"awardValueText":null,"detailIssue":null,"sourceQuery":"status open","source":"capt.gov.kw","country":"Kuwait","scrapedAt":"2026-11-09T21:37:46+00:00"}
```

### Limits and caveats

- The open-tender list and the award list are the current windows: about five pages each, newest first. Read the lists on a schedule to keep a complete history.
- Keyword and entity filters are matched against the published text, so they follow the language of the source: most tender subjects are in Arabic, while entity names are in English.
- The tender documents and the online purchase of documents stay in the CAPT company account; the Actor delivers the public listing data.
- If the source cannot be read, the run stops with a plain status message; rows already collected stay in the dataset.
- If nothing matches, the run succeeds with an empty dataset.

### FAQ

**How fresh is the data?** Every run reads the CAPT listings live.

**How do I get only new tenders each day?** Set `onlyNewSinceLastRun` and schedule a daily run. Deduplicate across runs on `tenderNumber` and `buyer` if you prefer to manage the state yourself.

**Do I need a CAPT account?** No. Tenders, award results, fees, bonds, meeting details and classifications are public.

**What happens when nothing matches?** The run succeeds with 0 rows and a plain status message.

**What if one tender's extra panels fail?** The row is still delivered with `detailIssue` set.

### Price

Each saved tender is one result. When a per-event plan applies, the start event is charged per GB of memory; the default 512 MB run is one start event. The start is charged even when a search saves nothing. See the Pricing tab for current prices.

### Custom sources and support

Need another Gulf or Saudi tender portal, a custom field, or a bulk or daily feed? Email automat42@outlook.com. For questions or issues, you can also contact us from the Actor page.

# Actor input Schema

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

Text matched in the tender subject or notes, as published (most subjects are in Arabic), e.g. 'صيانة' (maintenance). Up to 200 characters.

## `buyer` (type: `string`):

Part of the purchasing entity name, e.g. 'Ministry of Health' or 'Kuwait Municipality'. Up to 200 characters.

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

Which CAPT list to read: tenders open for bidding, or awarded contracts.

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

Earliest publication date, YYYY-MM-DD (inclusive). For awarded tenders this is the award meeting date.

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

Latest publication date, YYYY-MM-DD (inclusive). For awarded tenders this is the award meeting date.

## `closingFrom` (type: `string`):

Only open tenders whose offer deadline falls on or after this date, YYYY-MM-DD. Open tenders only.

## `closingTo` (type: `string`):

Only open tenders whose offer deadline falls on or before this date, YYYY-MM-DD. Open tenders only.

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

Stop after this many tenders (deduplicated on tender number and buying entity).

## `includeDetails` (type: `boolean`):

Read each open tender's initial-meeting and classification panels: meeting date and place, and the required classification types (two extra reads per tender). For awarded tenders split into items, read the items panel with each winner (one extra read). A failed panel keeps the row with detailIssue set.

## `onlyNewSinceLastRun` (type: `boolean`):

Keep a ledger in your Apify account and deliver only tenders that are new, or whose deadline, status, value or documents changed since the last run. A first run delivers everything.

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

Optional name for this search's ledger, e.g. 'health-maintenance'. Defaults to a key derived from the filters, so different searches keep separate ledgers. Up to 100 characters.

## Actor input object example

```json
{
  "keyword": "",
  "buyer": "",
  "status": "open",
  "publishedFrom": "",
  "publishedTo": "",
  "closingFrom": "",
  "closingTo": "",
  "maxItems": 20,
  "includeDetails": true,
  "onlyNewSinceLastRun": false,
  "stateKey": ""
}
```

# Actor output Schema

## `results` (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 = {
    "keyword": "",
    "buyer": "",
    "status": "open",
    "publishedFrom": "",
    "publishedTo": "",
    "closingFrom": "",
    "closingTo": "",
    "maxItems": 20,
    "includeDetails": true,
    "onlyNewSinceLastRun": false,
    "stateKey": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("automatic/kuwait-capt-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 = {
    "keyword": "",
    "buyer": "",
    "status": "open",
    "publishedFrom": "",
    "publishedTo": "",
    "closingFrom": "",
    "closingTo": "",
    "maxItems": 20,
    "includeDetails": True,
    "onlyNewSinceLastRun": False,
    "stateKey": "",
}

# Run the Actor and wait for it to finish
run = client.actor("automatic/kuwait-capt-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 '{
  "keyword": "",
  "buyer": "",
  "status": "open",
  "publishedFrom": "",
  "publishedTo": "",
  "closingFrom": "",
  "closingTo": "",
  "maxItems": 20,
  "includeDetails": true,
  "onlyNewSinceLastRun": false,
  "stateKey": ""
}' |
apify call automatic/kuwait-capt-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automatic/kuwait-capt-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/gbkxoQwJvpYbJggPd/builds/HLNvZEQq7E90lqSaq/openapi.json
