# PNCP Licitações API: Brazil Tenders, Values, Files (`actose/brazil-pncp-tenders`) Actor

Brazilian public tenders (licitações) from PNCP: agency, CNPJ, object, modality, estimated value, deadlines, edital files, line items. Filter by keyword, UF, modality, dates; onlyNew alerts. No API key, no login. MCP-ready for AI agents. Errors and empty results are free. $2 per 1,000 tenders

- **URL**: https://apify.com/actose/brazil-pncp-tenders.md
- **Developed by:** [ABM](https://apify.com/actose) (community)
- **Categories:** Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 90.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 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.
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

## PNCP Licitações API: Brazil Public Tenders Scraper

**$2 per 1,000 tenders. You pay only for tenders delivered: errors and empty results are free. No API key, no login, no monthly rental.**

This Actor searches **PNCP (Portal Nacional de Contratações Públicas)**, the official national portal where every Brazilian public body (federal, state and municipal) must publish its procurement under Lei 14.133/2021. It returns one clean JSON object per tender (licitação, pregão, dispensa, concorrência...) with:

- agency name, **CNPJ**, sphere (federal / state / municipal), unit, city, IBGE code, UF
- title, purchase object (objeto), purchase and process numbers, modality, dispute mode, status
- **estimated value** (valor total estimado) and approved value (homologado), in BRL
- publication date, **proposal opening date and deadline**
- **attachments**: edital, termo de referência, ETP... with direct download links
- optional **line items** (itens): description, quantity, unit, unit and total estimated value
- a ready-to-use **Markdown summary** for LLMs, RAG and alerts

Filter by **keyword**, **state (UF)**, **modality** and **publication date window**. Turn on **onlyNew** for daily monitoring: each scheduled run returns only tenders you have not received yet.

It reads PNCP's public JSON APIs directly (no browser, no HTML parsing), so it is fast and stable.

### How much does it cost?

Pay per event: **$0.002 per tender delivered** (`tender-result`).

| Run | Tenders | Price |
|---|---|---|
| Daily alert, 1 keyword, 1 state | ~20 | $0.04 |
| Weekly market scan | 250 | $0.50 |
| Bulk export | 1,000 | **$2.00** |

Nothing is charged for tenders filtered out, duplicates across keywords, tenders already delivered (onlyNew), API errors or empty searches. Set a maximum charge on your run: the Actor stops cleanly when it is reached.

### Input

```json
{
  "keywords": ["software", "licença de uso"],
  "state": "SP",
  "modalities": ["6", "8"],
  "status": "open",
  "daysBack": 7,
  "maxResults": 100,
  "includeDetails": true,
  "includeItems": false,
  "onlyNew": false
}
```

| Field | Description |
|---|---|
| `keywords` | Full-text terms (Portuguese works best: `limpeza`, `merenda escolar`, `pavimentação`). One search per keyword, merged and de-duplicated. Empty = all tenders. |
| `state` / `states` | UF codes (`SP`, `RJ`, `MG`, `DF`...). Empty = all of Brazil. |
| `modalities` | `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. |
| `status` | `all` (default), `open` (still receiving proposals), `closed`. |
| `daysBack` | Published in the last N days (Brasília time). Default 7. |
| `dateFrom` / `dateTo` | Explicit publication window (`2026-10-01`). Overrides `daysBack`. |
| `maxResults` | Maximum tenders delivered (and charged), all keywords together. |
| `includeDetails` | Detail sheet + attachments (default `true`). |
| `includeItems` | Purchase line items (default `false`). |
| `onlyNew` | Skip tenders delivered by previous runs with the same filters. |

### Output

One object per tender in the dataset (export to JSON, CSV, Excel, XML or HTML):

```json
{
  "pncpId": "46177523000109-1-000278/2026",
  "url": "https://pncp.gov.br/app/editais/46177523000109/2026/278",
  "title": "Edital nº 73/2026-R",
  "object": "AQUISIÇÃO DE LICENÇA USO DE SOFTWARE — para atender à SEICOM",
  "documentType": "Edital",
  "purchaseNumber": "73/2026-R",
  "processNumber": "33244/2026-57",
  "year": 2026,
  "sequentialNumber": 278,
  "modalityId": 6,
  "modality": "Pregão - Eletrônico",
  "disputeMode": "Aberto",
  "status": "Divulgada no PNCP",
  "cancelled": false,
  "publishedAt": "2026-10-20T16:26:19",
  "proposalOpeningDate": "2026-10-21T18:00:00",
  "proposalDeadline": "2026-11-10T08:00:00",
  "estimatedValue": 79179.48,
  "approvedValue": null,
  "currency": "BRL",
  "confidentialBudget": false,
  "agencyCnpj": "46177523000109",
  "agencyName": "MUNICIPIO DE SAO VICENTE",
  "agencySphere": "Municipal",
  "municipality": "São Vicente",
  "ibgeCode": "3551009",
  "state": "SP",
  "stateName": "São Paulo",
  "legalBasis": "Lei 14.133/2021, Art. 28, I",
  "priceRegistration": false,
  "publishedBy": "Novo BBMNET Licitações",
  "attachments": [
    {
      "title": "EDITAL__PE_732026_R__Licenca_Adobeampla",
      "documentType": "Edital",
      "documentTypeId": 2,
      "sequence": 1,
      "publishedAt": "2026-10-20T16:26:19",
      "url": "https://pncp.gov.br/pncp-api/v1/orgaos/46177523000109/compras/2026/278/arquivos/1"
    },
    {
      "title": "TR_Adobedocx",
      "documentType": "Termo de Referência",
      "url": "https://pncp.gov.br/pncp-api/v1/orgaos/46177523000109/compras/2026/278/arquivos/2"
    }
  ],
  "attachmentsCount": 5,
  "lineItems": [],
  "searchKeyword": "software",
  "detailsFetched": true,
  "markdown": "## Edital nº 73/2026-R – MUNICIPIO DE SAO VICENTE\n- **Modality:** Pregão - Eletrônico\n- **Estimated value:** BRL 79,179.48\n..."
}
```

With `includeItems: true`, `lineItems` contains for example
`{"number": 1, "description": "LICENÇA USO DE SOFTWARE ... Creative Cloud", "type": "Material", "quantity": 12, "unit": "LICENÇA", "unitEstimatedValue": 6598.29, "totalEstimatedValue": 79179.48, "judgmentCriterion": "Menor preço"}`.

Attachment links point to the official PNCP file server: download them directly. The Actor does not copy the files, so you don't pay storage.

### Use cases

#### 1. Daily IT tender alert for a software reseller (bid manager)

Every morning at 7:00, a bid manager at a São Paulo software reseller gets the new IT tenders in SP and RJ, still open for proposals, in Google Sheets.
Input:

```json
{"keywords": ["software", "licença de uso", "computadores"], "states": ["SP", "RJ"], "status": "open", "daysBack": 2, "onlyNew": true, "maxResults": 200}
```

Output (excerpt):

```json
[{"title": "Edital nº 73/2026-R", "agencyName": "MUNICIPIO DE SAO VICENTE", "estimatedValue": 79179.48, "proposalDeadline": "2026-11-10T08:00:00", "url": "https://pncp.gov.br/app/editais/46177523000109/2026/278"}]
```

About 15 to 40 new tenders per day, so $0.03 to $0.08 per day. The team qualifies them in the sheet and downloads the edital from `attachments[0].url`.

#### 2. Market sizing for a facility-services company (business analyst)

An analyst estimates the yearly public spend on cleaning in Minas Gerais from reverse auctions.
Input:

```json
{"keywords": ["limpeza", "conservação predial"], "state": "MG", "modalities": ["6", "7"], "dateFrom": "2026-07-01", "dateTo": "2026-09-30", "maxResults": 2000, "includeItems": true}
```

Output (excerpt):

```json
[{"agencyName": "MUNICIPIO DE ...", "municipality": "Uberlândia", "estimatedValue": 1250000.0, "lineItems": [{"description": "Serviço de limpeza ...", "quantity": 12, "unit": "MÊS"}]}]
```

About 1,500 tenders for $3. The CSV goes to Excel or BI to sum `estimatedValue` by municipality and find the biggest buyers by `agencyCnpj`.

#### 3. AI agent that drafts go/no-go notes (consultancy)

A public-procurement consultancy lets its AI agent (Claude through MCP) pull new direct awards and electronic auctions for "consultoria", then summarize each `markdown` field into a go/no-go note for its clients.
Input:

```json
{"keywords": ["consultoria"], "modalities": ["6", "8"], "daysBack": 1, "maxResults": 50}
```

Output (excerpt):

```json
[{"pncpId": "...-1-000045/2026", "modality": "Dispensa de Licitação", "markdown": "## Aviso de Contratação Direta nº 12/2026 – ...\n- **Estimated value:** BRL 48,000.00 ..."}]
```

50 tenders cost $0.10. The `markdown` field fits straight into the prompt, with no HTML to clean.

### Call it from the API

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<username>/brazil-pncp-tenders").call(run_input={
    "keywords": ["software"], "state": "SP", "status": "open", "daysBack": 7, "maxResults": 100,
})
for tender in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(tender["publishedAt"], tender["agencyName"], tender["estimatedValue"], tender["url"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<username>/brazil-pncp-tenders').call({
    keywords: ['software'], state: 'SP', status: 'open', daysBack: 7, maxResults: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((t) => `${t.agencyName} | ${t.estimatedValue} | ${t.url}`));
```

### Automation (Make, n8n, Zapier, Google Sheets)

- **Make / n8n / Zapier**: add a *Schedule* trigger (every day at 7:00), then *Apify → Run Actor* with the input of use case 1 (`onlyNew: true`), then *Apify → Get dataset items*, then *Google Sheets → Add rows* (columns `publishedAt`, `title`, `agencyName`, `state`, `estimatedValue`, `proposalDeadline`, `url`). You can add a *Slack* or *Email* step that sends the `markdown` field.
- **Apify Schedules + integrations**: schedule the Actor in the Apify Console and connect the Google Sheets or Slack integration with no code.
- **Webhooks**: send `ACTOR.RUN.SUCCEEDED` to your own endpoint and fetch the dataset.

### Use with AI agents (MCP)

The Actor works with the Apify MCP server (`https://mcp.apify.com`) from Claude, Cursor, ChatGPT and other MCP clients. Ask for example: *"Find open pregões for software in São Paulo published this week and list the ones above R$ 100,000."* The agent fills in `keywords`, `state`, `status` and `daysBack`, and reads `markdown` or the structured fields.

### FAQ

**Is this legal?** Yes. PNCP is an official open-data portal of the Brazilian federal government, and the Actor only reads its public APIs. It never logs in and never solves captchas. It connects directly; only if PNCP refuses the server's IP does it fall back to an Apify proxy (datacenter first), at no extra cost to you.

**Which tenders are covered?** Everything published on PNCP as a "contratação" (edital or aviso): pregão, concorrência, dispensa, inexigibilidade, leilão, credenciamento... Since Lei 14.133/2021, publication on PNCP is mandatory for every public body, but some municipalities still publish late or only on their own portal.

**Why is `estimatedValue` null?** The agency marked the budget as confidential (`confidentialBudget: true`, orçamento sigiloso). This is allowed by law until the auction ends.

**How does onlyNew work?** IDs already delivered for the same keywords, states, modalities and status are remembered for 120 days in a named key-value store of your account. Schedule the Actor daily with `daysBack: 2` so you never miss a late publication.

**Keywords in English?** PNCP texts are in Portuguese. `software` works, but `limpeza` will find much more than `cleaning`.

**Can I get contract awards and suppliers?** `hasResult` and `approvedValue` show whether a result was registered. Full contract and supplier data is out of scope for this Actor.

### Limits

- Search is full-text across title, object and agency, so a keyword may also match the agency name or a related word.
- `maxResults` applies to all keywords together. Keywords are processed in order, so the first ones can use up the quota.
- The publication-window scan goes through at most 10,000 search hits per keyword (newest first). For an old window with a very broad query, narrow the filters (state, modality, keyword).
- Two official sources, automatic switch: the PNCP full-text search API is tried first; when it is down or resets connections (it often does), the Actor switches within seconds to the official PNCP consulta API (`/contratacoes/publicacao`), scans the date window by state and modality and matches every keyword on the object, notes and agency names (accent-insensitive, all words of the keyword must appear). Same tenders, same output fields; the run never fails because of the search API.
- In that fallback mode, a nationwide search (no state) over a long window reads many pages: add a state or modality filter for faster runs. Tenders are then not strictly newest first.
- PNCP sometimes resets connections or returns 5xx errors. The Actor retries with backoff. If a detail sheet still fails, the tender is delivered with its search fields only (`detailsFetched: false`).
- Attachment files are linked, not downloaded.
- Windows longer than one year are split automatically into 365-day chunks, because the official API refuses longer windows.
- When the run is about to reach its timeout, the Actor stops scanning and delivers what it already found. Tenders delivered in the last seconds may have no attachment list (`attachmentsCount: null`). For long windows, raise the run timeout.
- If PNCP is completely down, the run ends with a clear status message and nothing is charged. Retry a few minutes later.

# Actor input Schema

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

Full-text search terms, in Portuguese for best results (e.g. "software", "limpeza", "merenda escolar", "pavimentação"). Each keyword is a separate search; duplicates across keywords are removed. Leave empty to get every tender matching the other filters.

## `state` (type: `string`):

Two-letter Brazilian state code (UF) of the buying agency, e.g. SP, RJ, MG, DF. Leave empty for all of Brazil.

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

Optional: several UF codes at once (e.g. \["RJ", "MG"]). Combined with "State".

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

Procurement modalities to keep. Leave empty for all.

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

"open" = still receiving proposals (recebendo proposta), "closed" = proposals closed (encerradas), "all" = every status (including suspended, revoked, cancelled).

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

Keep tenders published on PNCP in the last N days (Brasília time). Ignored when "Published from" is set. 0 = today only.

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

Optional start of the publication window, e.g. 2026-10-01. Overrides "daysBack".

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

Optional end of the publication window (inclusive). Default: today.

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

Maximum number of tenders delivered (and charged) in this run, all keywords together.

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

Fetch the official detail sheet (process number, proposal opening/closing dates, estimated and approved value, legal basis) and the list of attached documents (edital, termo de referência, ETP...) with direct download links.

## `includeItems` (type: `boolean`):

Also fetch the purchase line items: description, quantity, unit, unit and total estimated value. Slower (one or more extra requests per tender).

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

For scheduled daily monitoring: skip tenders already delivered by a previous run with the same keywords, states, modalities and status (remembered in a named key-value store for 120 days). You only pay for new tenders.

## Actor input object example

```json
{
  "keywords": [
    "software",
    "licença de uso"
  ],
  "state": "SP",
  "states": [
    "RJ",
    "MG"
  ],
  "modalities": [
    "6",
    "8"
  ],
  "status": "all",
  "daysBack": 7,
  "maxResults": 50,
  "includeDetails": true,
  "includeItems": false,
  "onlyNew": false
}
```

# Actor output Schema

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

One item per PNCP tender (overview table).

## `tendersJson` (type: `string`):

Every field of every tender, including attachments, line items and the Markdown summary.

# 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"
    ],
    "state": "SP",
    "daysBack": 7,
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("actose/brazil-pncp-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 = {
    "keywords": ["software"],
    "state": "SP",
    "daysBack": 7,
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("actose/brazil-pncp-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 '{
  "keywords": [
    "software"
  ],
  "state": "SP",
  "daysBack": 7,
  "maxResults": 50
}' |
apify call actose/brazil-pncp-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,actose/brazil-pncp-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/IAU3iePF7y2V2JIfx/builds/fvg7COBYSnuZhvQnX/openapi.json
