# Brazil Public Tenders Radar (PNCP) (`brasil-data/brazil-public-tenders-radar`) Actor

Search and monitor Brazilian public tenders (licitações) from the official PNCP API: keyword search without accents, state/city/modality/value filters, open-for-proposals only, and a monitor mode that returns only new tenders since the last run.

- **URL**: https://apify.com/brasil-data/brazil-public-tenders-radar.md
- **Developed by:** [Brasil Data](https://apify.com/brasil-data) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 tender delivereds

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

## Brazil Public Tenders Radar (PNCP)

Search and monitor **Brazilian public tenders (licitações)** published in the **PNCP – Portal Nacional de Contratações Públicas**, the official national procurement portal created by Brazil's procurement law (Lei 14.133/2021). Federal, state and municipal buyers must publish their tenders there.

The official PNCP API has no keyword search, requires one query per modality and paginates in blocks of 50. This Actor does the tedious part for you:

- **Keyword search in the tender object**, case- and accent-insensitive (`manutencao` finds `MANUTENÇÃO`), whole words, singular/plural, `constru*` prefix search.
- **Filters**: states (UF), IBGE municipality codes, official modality codes, publication window, estimated value range (BRL), only tenders still **open for proposals**.
- **Monitor mode**: give it a `monitor_id`, schedule it daily, and it returns **only tenders that are new since the last run** (deduplicated by the PNCP control number).
- Clean JSON in English `snake_case`, money as **decimal strings** (never floats), ISO 8601 dates, direct link to the official tender page and (optionally) to every tender document.
- Personal data protection (Brazil's LGPD): **CPF numbers of natural persons are removed** from the output.

### Who is it for

- Companies and consultants that sell to the Brazilian government and need daily tender alerts by theme.
- Developers and data teams building procurement dashboards, lead lists or market studies.
- **AI agents** that need fresh, structured Brazilian procurement data (see *Use with AI agents*).

### Input example

```json
{
  "mode": "search",
  "keywords": ["software", "licença de uso"],
  "states": ["SP", "MG"],
  "modalities": ["6", "4"],
  "only_open_for_proposals": true,
  "last_n_days": 7,
  "min_estimated_value_brl": 50000,
  "max_results": 200
}
```

Monitor (schedule it once a day in Apify Schedules):

```json
{
  "mode": "monitor",
  "monitor_id": "software-sp",
  "keywords": ["software"],
  "states": ["SP"],
  "last_n_days": 3
}
```

| Field | Description |
|---|---|
| `mode` | `search` (default) or `monitor` |
| `monitor_id` | Required in monitor mode; each ID keeps its own memory of delivered tenders |
| `keywords` | Words searched in the tender object; any keyword matches; empty = no keyword filter |
| `only_open_for_proposals` | Default `true`: only tenders whose proposal deadline is in the future (fast path). `false` searches the publication history (one API query per modality, slower) |
| `states` | UF codes (`SP`, `RJ`...) |
| `municipality_ibge_codes` | 7-digit IBGE codes; overrides `states` |
| `modalities` | Official PNCP codes: 1 Leilão Eletrônico, 2 Diálogo Competitivo, 3 Concurso, 4 Concorrência Eletrônica, 5 Concorrência Presencial, 6 Pregão Eletrônico, 7 Pregão Presencial, 8 Dispensa, 9 Inexigibilidade, 10 Manifestação de Interesse, 11 Pré-qualificação, 12 Credenciamento, 13 Leilão Presencial, 14 Inaplicabilidade, 15 Chamada Pública, 16-19 international Concorrência/Pregão |
| `last_n_days` / `published_from` / `published_to` | Publication window (Brasília time). Max 366 days per run |
| `min_estimated_value_brl` / `max_estimated_value_brl` | Estimated total value range; tenders without a public estimate are excluded when set |
| `max_results` | Max tenders delivered (and charged) per run |
| `include_file_links` | Also list the tender documents with download URLs (1 extra request per tender) |
| `max_pages` | Safety limit of API pages (50 records each) per run |

### Output example

One dataset item per tender (real record, shortened):

```json
{
  "pncp_control_number": "04005179000120-1-000076/2026",
  "title": "Edital 60/2026",
  "object": "REGISTRO DE PREÇOS PARA EVENTUAL AQUISIÇÃO DE MATERIAIS ELÉTRICOS, DUTOS E TUBOS DE CONCRETO ARMADO...",
  "matched_keywords": ["aquisicao"],
  "buyer_cnpj": "04005179000120",
  "buyer_name": "MUNICIPIO DE FEIJO",
  "buyer_sphere": "Municipal",
  "state": "AC",
  "municipality": "Feijó",
  "municipality_ibge_code": "1200302",
  "modality_code": 6,
  "modality_name": "Pregão - Eletrônico",
  "modality_name_en": "Electronic reverse auction (pregão)",
  "estimated_value_brl": "16859395.35",
  "currency": "BRL",
  "published_at": "2026-10-23T20:52:31-03:00",
  "proposals_open_at": "2026-10-27T10:00:00-03:00",
  "proposals_close_at": "2026-11-10T10:00:00-03:00",
  "status": "Divulgada no PNCP",
  "open_for_proposals": true,
  "tender_url": "https://pncp.gov.br/app/editais/04005179000120/2026/76",
  "files_api_url": "https://pncp.gov.br/api/pncp/v1/orgaos/04005179000120/compras/2026/76/arquivos",
  "files": [{"title": "10. EDITAL ATUALIZADO retificado.pdf", "document_type": "Edital", "url": "https://pncp.gov.br/pncp-api/v1/orgaos/04005179000120/compras/2026/76/arquivos/1"}],
  "source_url": "https://pncp.gov.br/api/consulta/v1/orgaos/04005179000120/compras/2026/76",
  "source_name": "PNCP - Portal Nacional de Contratações Públicas (Brazil, Lei 14.133/2021)",
  "retrieved_at": "2026-10-25T03:10:19Z",
  "data_license": "Brazilian open government data (Lei 14.133/2021 art. 174 §4; Decreto 8.777/2016 art. 4)"
}
```

Other fields: `additional_info`, `buyer_power`, `buying_unit_code/name`, `dispute_mode`, `instrument_type`, `purchase_number`, `process_number`, `is_price_registration`, `legal_basis`, `awarded_value_brl`, `updated_at`, `status_code`, `origin_system_url`, `electronic_process_url`, `terms_note`.

A run summary is saved as `OUTPUT` in the run's key-value store (`status`, `stop_reason`, `delivered`, `records_scanned`, `pages_fetched`, `warnings`).

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `tender-result` | USD 0.003 | per tender delivered to the dataset |
| `monitor-new-tenders` | USD 0.02 | once per **monitor** run that found at least one new tender |

You are **never charged** for empty runs, errors, source outages or tenders a monitor already delivered. Examples: 100 tenders = USD 0.30; a daily monitor with 5 new tenders = USD 0.035/day; a monitor run with no news = USD 0. The Actor stops as soon as your maximum charge per run is reached.

### Limits and good to know

- The PNCP API allows roughly one request every 1.6-2 seconds; each request returns up to 50 tenders. Keyword filtering happens on this side, so a nationwide history scan of many days can take minutes. Use `only_open_for_proposals: true` (default), states and modalities to keep runs fast.
- Results come newest first. Monitor mode keeps the IDs it delivered for 180 days (up to 50,000 per `monitor_id`) in a named key-value store of your account (`pncp-tenders-radar-monitor`). Undelivered tenders (for example when `max_results` was reached) are not marked as seen.
- Times are Brasília time (UTC-03:00), as published by the PNCP.
- Plural handling applies to the last word of each keyword (`material de limpeza` does not match `materiais de limpeza`; add both forms if needed).
- If the PNCP API is down, the run ends with a clear status message and no charge.

### Source, license and terms

- Source: official PNCP public consultation API — `https://pncp.gov.br/api/consulta` (Swagger: `https://pncp.gov.br/api/consulta/swagger-ui/index.html`), no login, no captcha.
- License: Brazilian open government data. Lei 14.133/2021, art. 174 §4 (the PNCP adopts the open data format) and Decreto 8.777/2016 (open data may be freely used, including commercially, limited to crediting the source). Attribution: *Fonte: PNCP – Portal Nacional de Contratações Públicas*.
- This Actor is independent and is not affiliated with or endorsed by the Brazilian government.

### Use with AI agents (MCP)

Every Apify Actor is available to AI agents through the Apify MCP server (`https://mcp.apify.com`). An agent (Claude, ChatGPT, Cursor and others) can call this Actor with a plain JSON input such as `{"keywords": ["software"], "states": ["SP"], "max_results": 20}` and receive structured tenders with stable English field names, decimal-string money and official links — ready for summarising, ranking or alerting. Monitor mode with a fixed `monitor_id` lets an agent ask "what is new since yesterday?" without keeping its own memory.

***

### Em português (resumo)

**Radar de licitações do PNCP.** Busca e monitora licitações e contratações públicas publicadas no Portal Nacional de Contratações Públicas (Lei 14.133/2021), usando a API oficial de consulta.

- Busca por palavra-chave no objeto da compra, **sem diferenciar acento ou maiúscula** (`manutencao` encontra `MANUTENÇÃO`), com singular/plural e prefixo (`constru*`).
- Filtros por UF, código IBGE do município, modalidade oficial, período de publicação, faixa de valor estimado e **somente propostas em aberto**.
- **Modo monitor**: escolha um `monitor_id`, agende a execução diária e receba **só os editais novos** desde a última execução.
- Valores em string decimal, datas ISO 8601 (horário de Brasília), link oficial do edital e dos arquivos.
- LGPD: CPF de pessoa física é removido da saída.
- Preço: US$ 0,003 por edital entregue; US$ 0,02 por execução de monitor que encontrou novidade. Execução vazia ou com erro não é cobrada.
- Fonte: PNCP, dados abertos (Lei 14.133/2021, art. 174 §4; Decreto 8.777/2016). Ferramenta independente, sem vínculo com o governo.

# Actor input Schema

## `mode` (type: `string`):

'search' returns every matching tender. 'monitor' remembers the tenders already delivered (per monitor_id) and returns ONLY new ones since the previous run - schedule it daily for alerts.

## `monitor_id` (type: `string`):

Required in monitor mode. A name you choose for this alert (letters, digits, '-' and '\_'), e.g. 'software-sp'. Each ID keeps its own memory of delivered tenders.

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

Words searched in the tender object (objeto da compra). Case- and accent-insensitive ('manutencao' finds 'MANUTENÇÃO'), whole words, singular/plural accepted. End a word with \* for prefix search (e.g. 'constru\*'). A tender matches if ANY keyword matches. Leave empty to list all tenders for the other filters.

## `only_open_for_proposals` (type: `boolean`):

Keep only tenders whose proposal deadline is still in the future (uses the PNCP 'open for proposals' endpoint, the fastest way to scan all modalities). Turn off to search the publication history (slower: the PNCP API requires one query per modality).

## `states` (type: `array`):

Limit to these Brazilian states. Empty = whole country. Ignored when municipality codes are given.

## `municipality_ibge_codes` (type: `array`):

7-digit IBGE codes of the cities where the buying unit is located, e.g. 3550308 (São Paulo), 3304557 (Rio de Janeiro). When set, 'States' is ignored.

## `modalities` (type: `array`):

Official PNCP procurement modality codes (Lei 14.133/2021). Empty = all modalities.

## `last_n_days` (type: `integer`):

Publication window when 'Published from' is empty: tenders published in the last N days (Brasília time).

## `published_from` (type: `string`):

Start of the publication window (inclusive). Overrides 'last N days'.

## `published_to` (type: `string`):

End of the publication window (inclusive). Default: now.

## `min_estimated_value_brl` (type: `integer`):

Keep tenders whose total estimated value is at least this amount. Tenders without a public estimate (e.g. confidential budget) are excluded when a value filter is set.

## `max_estimated_value_brl` (type: `integer`):

Keep tenders whose total estimated value is at most this amount.

## `max_results` (type: `integer`):

Maximum number of tenders delivered (and charged) in this run.

## `include_file_links` (type: `boolean`):

Also list the tender documents (edital, termo de referência...) with direct download URLs. Costs one extra API request per tender, so runs are slower.

## `max_pages` (type: `integer`):

Safety limit: maximum PNCP API pages (50 records each) read in this run. The PNCP API has no full-text search, so keyword filtering happens on this side; the official API allows ~1 request every 1.6-2 s.

## Actor input object example

```json
{
  "mode": "search",
  "monitor_id": "software-sp",
  "keywords": [
    "software",
    "licença de uso",
    "manutenção predial"
  ],
  "only_open_for_proposals": true,
  "states": [
    "SP",
    "RJ"
  ],
  "municipality_ibge_codes": [
    "3550308"
  ],
  "modalities": [
    "6",
    "4"
  ],
  "last_n_days": 3,
  "max_results": 10,
  "include_file_links": false,
  "max_pages": 300
}
```

# Actor output Schema

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

Public tenders (PNCP) that matched your filters, in the default dataset.

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

Counts, warnings and data version for this run (key-value store record OUTPUT, when present).

# 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"
    ],
    "last_n_days": 3,
    "max_results": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("brasil-data/brazil-public-tenders-radar").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"],
    "last_n_days": 3,
    "max_results": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("brasil-data/brazil-public-tenders-radar").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"
  ],
  "last_n_days": 3,
  "max_results": 10
}' |
apify call brasil-data/brazil-public-tenders-radar --silent --output-dataset

```

## MCP server setup

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

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/UXHWrxNjXIKdef5Jf/builds/LtoV3dkZxFwdTqvMD/openapi.json
