# PNCP Brazil Public Tenders & Contracts (Licitações) API (`jpopendata/brazil-pncp-tenders`) Actor

Brazil's public tenders (licitações) and contracts from the official PNCP API: open tenders, new tenders and signed contracts with buyer, CNPJ, state, city, method, deadline, value in BRL and supplier companies. English labels. Unofficial; not affiliated with PNCP.

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

## Pricing

from $2.00 / 1,000 results

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

## PNCP Brazil Public Tenders & Contracts (Licitações) API

Get **Brazilian public procurement** from **PNCP** (Portal Nacional de Contratações Públicas), the official national portal where every federal, state and municipal body must publish its tenders and contracts under Lei 14.133/2021. Three things in one Actor:

- **Open tenders** — licitações whose proposal period is open now (live opportunities, closing within N days);
- **New tenders** — everything published in a date window (pregão, concorrência, dispensa, inexigibilidade, credenciamento, leilão ...);
- **Contracts** — signed contracts and empenhos, with the **supplier company and its CNPJ**.

Data comes live from PNCP's **official consultation API** (no login, no API key, no browser). Every row has **English labels next to PNCP's Portuguese ones**, and shared fields use the same names as our UK, EU (TED), US (SAM.gov) and Australian (AusTender) tender Actors — `title`, `buyerName`, `procurementMethod`, `valueAmount`, `tenderDeadline`, `contractStart` / `contractEnd`, `awardedSuppliers`, `noticeUrl` — so the datasets are easy to combine.

> **Unofficial tool. Not affiliated with or endorsed by the Government of Brazil, the Ministério da Gestão e da Inovação em Serviços Públicos or PNCP.** It reads PNCP's public open-data API only, politely (one request at a time, at least 5 seconds apart, a hard request budget, no block evasion), and outputs procurement facts only — no personal data (see "Personal data" below). You are responsible for making sure your use of the data complies with applicable law (including the LGPD).

### Quick start — verified input

Open electronic reverse auctions (pregão eletrônico) in São Paulo state, newest first:

```json
{
  "mode": "open",
  "states": ["SP"],
  "procurementMethods": ["pregao-electronic"],
  "maxItems": 20
}
```

An empty input `{}` also works: the newest 20 tenders published in the last 3 days, nationwide, all procurement methods.

More examples:

```json
{
  "mode": "published",
  "daysBack": 1,
  "keywords": ["computador", "notebook", "software"],
  "states": ["MG", "RJ"],
  "maxItems": 500,
  "maxApiRequests": 200
}
```

```json
{
  "mode": "contracts",
  "dateFrom": "2026-10-01",
  "dateTo": "2026-10-07",
  "buyerCnpjs": ["00394544000185"],
  "valueMin": 100000,
  "maxItems": 200
}
```

```json
{
  "mode": "open",
  "cities": ["Campinas - SP", "Belo Horizonte - MG"],
  "daysAhead": 15,
  "keywords": ["obra", "pavimentação"],
  "maxItems": 100
}
```

### Input

| Field | Example | What it does |
|---|---|---|
| `mode` | `"open"` | `published` (tenders published in the date window, default), `open` (tenders open for proposals now), `contracts` (contracts published in the date window). |
| `keywords` | `["medicamento", "merenda escolar"]` | Words or phrases in the object (title), buyer, buying unit and supplier name; any case, accents ignored, matched at the **start of words** (`computador` also finds `computadores`). Titles are in Portuguese. Any keyword matches. |
| `states` | `["SP", "Minas Gerais"]` | States (UF) of the buying unit. |
| `cities` | `["Campinas - SP", "3550308"]` | Municipalities as `City - UF`, IBGE code, or a name that is unique in Brazil. A row matches any listed state **or** city. |
| `buyerCnpjs` | `["00394544000185"]` | CNPJ of the buying body (punctuation optional; check digits are verified, alphanumeric CNPJs accepted). |
| `procurementMethods` | `["6", "dispensa"]` | PNCP modalidade codes or names (tenders only): 6 Pregão eletrônico, 8 Dispensa, 9 Inexigibilidade, 4 Concorrência eletrônica, 12 Credenciamento, 7 Pregão presencial, 1 Leilão eletrônico, 5 Concorrência presencial, 3 Concurso, 2 Diálogo competitivo, 10 Manifestação de interesse, 11 Pré-qualificação, 13 Leilão presencial. `pregao` = 6 and 7. |
| `daysBack` | `7` | published / contracts: from N days ago up to today (Brasília calendar days). Default 3. |
| `daysAhead` | `15` | open: proposal period closes within the next N days. Default 30. |
| `dateFrom` / `dateTo` | `"2026-09-01"`, `"30/09/2026"` | Explicit window (max 366 days). In `open` mode `dateTo` is the last closing day. `YYYY-MM-DD`, `DD/MM/YYYY`, `today`, `-30d`, `+15d` work. |
| `valueMin` / `valueMax` | `100000` | BRL. Estimated value for tenders, global (else initial) value for contracts. Rows without a value are dropped when a range is set. |
| `maxItems` | `20` | Maximum rows (1–10,000). You are charged per row. |
| `maxApiRequests` | `40` | Hard request budget (1–1,000). Requests are at least 5 s apart; one request returns up to 50 tenders or 500 contracts. |

#### Common input mistakes

| Wrong | Right | Why |
|---|---|---|
| `"keywords": ["laptop"]` | `"keywords": ["notebook", "computador"]` | Titles are written in Portuguese. |
| `"cities": ["Campinas"]` meaning several | `"cities": ["Campinas - SP"]` | Add the UF when a name exists in several states (the error lists them). |
| `"states": ["São Paulo city"]` | `"cities": ["São Paulo - SP"]` | States and cities are separate fields. |
| `"procurementMethods": ["RFP"]` | `"procurementMethods": ["6"]` | Use PNCP's modalidades (the error lists all 13). |
| `"buyerCnpjs": ["Universidade de São Paulo"]` | `"buyerCnpjs": ["63025530000104"]` | Names are not accepted; use the CNPJ shown on PNCP (keywords for words). |
| a big nationwide keyword search with the default budget | raise `maxApiRequests`, add `states` or `procurementMethods` | Keyword matching happens on the rows PNCP returns; PNCP itself has no keyword search. |

An invalid value stops the run immediately, before any request to PNCP, with a message that names the field and lists the valid values. Numbers outside their range are clamped with a warning.

### Output example

One dataset item per PNCP record (a tender = "contratação", or a contract):

```json
{
  "id": "12248878000120-1-000022/2026",
  "recordType": "tender",
  "stage": "tender",
  "status": "open",
  "statusOriginal": "Divulgada no PNCP",
  "isOpenForBids": true,
  "title": "CONTRATAÇÃO DE PESSOA JURÍDICA ESPECIALIZADA NO FORNECIMENTO DE 01 (UM) CAMINHÃO TRUCADO BASCULANTE ...",
  "buyerName": "MUNICIPIO DE NOVO LINO",
  "buyerCnpj": "12248878000120",
  "buyerSphere": "municipal",
  "buyerUnitName": "PREFEITURA MUNICIPAL DE NOVO LINO - AL",
  "buyerState": "AL",
  "buyerStateName": "Alagoas",
  "buyerCity": "Novo Lino",
  "buyerCityIbgeCode": "2705606",
  "procurementMethod": "Reverse auction (pregão), electronic",
  "procurementMethodCode": 6,
  "procurementMethodOriginal": "Pregão - Eletrônico",
  "disputeMode": "Open bidding",
  "disputeModeOriginal": "Aberto",
  "instrumentType": "Call for tenders (edital)",
  "legalBasis": "Lei 14.133/2021, Art. 28, I",
  "priceRegistration": false,
  "valueAmount": 648000,
  "valueCurrency": "BRL",
  "valueUndisclosed": false,
  "tenderDeadline": "2026-10-21T10:00:00-03:00",
  "bidsOpenFrom": "2026-10-11T00:00:00-03:00",
  "daysUntilDeadline": 8,
  "purchaseNumber": "012/2026 (2º chamada)",
  "processNumber": "5000062300022026",
  "publishedDate": "2026-10-10",
  "publishedAt": "2026-10-10T21:10:27-03:00",
  "sourceSystemUrl": "https://bnccompras.com/Process/ProcessView?param1=...",
  "noticeUrl": "https://pncp.gov.br/app/editais/12248878000120/2026/22",
  "supplierName": null,
  "awardedSuppliers": [],
  "matchedKeywords": [],
  "source": "PNCP - Portal Nacional de Contratações Públicas (Brazil), official consultation API",
  "sourceUrl": "https://pncp.gov.br/",
  "license": "Source: Portal Nacional de Contratações Públicas (PNCP), https://pncp.gov.br - Brazilian public procurement open data ...",
  "retrievedAt": "2026-10-12T23:40:17.096Z"
}
```

A contract row fills `contractNumber`, `contractType` (+ `contractTypeOriginal`), `processCategory`, `contractInitialValue`, `contractGlobalValue`, `signedDate`, `contractStart`, `contractEnd`, `isRevenue`, `relatedTenderId` (the PNCP ID of the tender it came from) and `supplierName` / `supplierCnpj` / `supplierType` when the supplier is a company. Every row has every field (`null` when PNCP has no value or it does not apply).

#### Main fields

- `id` — PNCP control number (tender `...-1-.../year`, contract `...-2-.../year`); `noticeUrl` opens the record on the PNCP portal; `sourceSystemUrl` is the buying platform where proposals are submitted (tenders).
- `status` — tenders: `open` (proposal period not over), `closed` (period over, no result yet), `awarded` (result homologated), `suspended`, `cancelled` (revoked or annulled), `unknown`; contracts: `awarded`. `statusOriginal` is PNCP's situação.
- `valueAmount` — tenders: estimated value; contracts: global (else initial) value; BRL. `valueUndisclosed: true` means PNCP returned 0, which it does for confidential budgets (orçamento sigiloso) without a result.
- `awardedValue` — tenders: homologated value; contracts: global (else initial) value.
- `tenderDeadline` / `bidsOpenFrom` — proposal period, ISO 8601 with the Brasília offset (`-03:00`). `daysUntilDeadline` is counted when the run read the row.
- `...Original` fields keep PNCP's Portuguese labels; the English fields come from PNCP's code tables. The title (`objeto`) is not translated.

### How it works

1. `published` asks `/v1/contratacoes/publicacao` once per procurement method (PNCP requires one) and per state/city/buyer you set; `open` asks `/v1/contratacoes/proposta`; `contracts` asks `/v1/contratos` (PNCP has no state filter for contracts, so states and cities are applied to its results).
2. Each query is read **newest first** (PNCP lists oldest first, so the Actor reads the last page first). A window with more than 1,000 rows is read one day at a time, newest day first.
3. Every row is normalised, de-duplicated by its PNCP ID and checked again against every filter (PNCP silently ignores parameters it does not support).
4. `RUN_SUMMARY` (key-value store) records the queries, pages, rows read and filtered, withheld suppliers, request count, `complete` and a `stopReason`.

### Empty results?

A search with no match ends with 0 rows and `complete: true` — not an error. Typical causes: a weekend or holiday window (bodies publish on working days), a keyword in English, or a small city combined with one method and a value range. Widen the window, use Portuguese words or relax the filters.

If PNCP refuses requests mid-run (HTTP 429/5xx after the allowed waits) or the budget runs out, the run keeps what it found and ends successfully with `complete: false`. If the very first request fails, the run fails visibly instead of retrying aggressively.

### Personal data (LGPD / GDPR)

PNCP publishes contract suppliers with their identifier — including **natural persons with their full CPF** and **sole traders** (MEI / empresário individual) whose business name is their own name. This Actor shows a supplier's name and CNPJ **only when the supplier is a legal entity** (LTDA, S.A., EIRELI, cooperatives, associations, foundations, public bodies ...). Individuals, MEI-format names (`<CNPJ root> <owner's name>`), names containing a CPF and names without legal-entity evidence are withheld: `supplierName` and `supplierCnpj` are `null` and `supplierNameWithheld` is `true` (some companies without a legal-form word are withheld too — we prefer that to publishing a person's name). When a supplier is withheld, its name words and identifier are also removed from that contract's text.

The Actor never outputs PNCP's free-text "informação complementar" (which often names officials), the publishing platform user, subcontractors, e-mail addresses or phone numbers; CPF numbers, contacts and "title + name" sequences inside titles are replaced.

### Source, licence and attribution

Source: Portal Nacional de Contratações Públicas (PNCP), https://pncp.gov.br. PNCP is the official portal created by Lei 14.133/2021 (art. 174), which must adopt the open-data format and the requirements of the Access to Information Law (Lei 12.527/2011). Open data published by the Brazilian federal Executive are free to use with credit to the source (Decreto 8.777/2016, arts. 2 and 4). Records are entered by the contracting bodies, which are responsible for them; verify important details on PNCP. Each row carries this credit in `source`, `sourceUrl` and `license`.

### Disclaimer

Unofficial tool, not affiliated with or endorsed by the Government of Brazil, the Ministério da Gestão e da Inovação em Serviços Públicos, SERPRO or PNCP. Data are provided as published by PNCP at retrieval time (`retrievedAt`), without warranty. This is not legal advice.

# Actor input Schema

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

published = tenders published on PNCP in the date window (default); open = tenders whose proposal period is open now and closes by Days ahead / Date to (live opportunities; suspended, revoked and annulled ones are left out); contracts = contracts and contract-like commitments published in the date window, with the supplier when it is a company.

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

Optional. Words or phrases searched in the object (title), the buyer and its unit and the supplier name, any case, accents ignored, at the start of words: "computador" also finds "computadores". Titles are in Portuguese, e.g. "medicamento", "merenda escolar", "obra", "software", "veículo". A record matches if it contains ANY of them. Leave empty for all records.

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

Optional. States of the buying unit: AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO (full names such as "Minas Gerais" work too). Empty = all of Brazil.

## `cities` (type: `array`):

Optional. Municipalities of the buying unit as "City - UF" ("Campinas - SP"), the IBGE code ("3509502") or a name that is unique in Brazil. A record matches if it is in any listed state OR any listed city.

## `buyerCnpjs` (type: `array`):

Optional. CNPJ of the buying body (órgão / entidade), 14 characters, punctuation optional, e.g. "63.025.530/0001-04" (Universidade de São Paulo) or "00394544000185" (Ministério da Saúde).

## `procurementMethods` (type: `array`):

Optional, tenders only. PNCP codes or names: 6 Pregão eletrônico, 8 Dispensa, 9 Inexigibilidade, 4 Concorrência eletrônica, 12 Credenciamento, 7 Pregão presencial, 1 Leilão eletrônico, 5 Concorrência presencial, 3 Concurso, 2 Diálogo competitivo, 10 Manifestação de interesse, 11 Pré-qualificação, 13 Leilão presencial. "pregao" means 6 and 7. Empty = all methods.

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

For published / contracts: search from N days ago up to today (1..366, Brasília calendar days). Ignored when Date from is set. PNCP receives thousands of tenders and contracts per working day; with Max rows the run stops early once it has enough.

## `daysAhead` (type: `integer`):

For open: tenders whose proposal period is open now and closes within the next N days (1..366). Ignored when Date to is set.

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

Optional (published / contracts). First publication day, YYYY-MM-DD, e.g. "2026-09-01". DD/MM/YYYY (day first), "today", "yesterday" and relative days such as "-30d" also work. The window can be at most 366 days.

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

Optional. published / contracts: last publication day (empty = today). open: the last proposal-closing day to include, e.g. "+15d" or "2026-11-30" (empty = today + Days ahead).

## `valueMin` (type: `integer`):

Optional. Minimum value in Brazilian reais: the estimated value for tenders, the global (else initial) value for contracts, e.g. 100000. Records without a value (including confidential budgets) are dropped when a value range is set.

## `valueMax` (type: `integer`):

Optional. Maximum value in Brazilian reais, e.g. 5000000.

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

Maximum rows (1..10000). Rows come newest first within each query (published / open: per procurement method). You are charged per row.

## `maxApiRequests` (type: `integer`):

Hard budget of requests to the PNCP API for the whole run (1..1000). Requests are sent one at a time at least 5 seconds apart; one request returns up to 50 tenders or 500 contracts. If the budget runs out the run still succeeds with what it found (complete=false in RUN_SUMMARY).

## `proxyConfiguration` (type: `object`):

Optional and normally not needed: the PNCP API answers Apify datacenter IPs. If set, one sticky session is used for the whole run (never rotation).

## Actor input object example

```json
{
  "mode": "published",
  "keywords": [],
  "states": [],
  "cities": [],
  "buyerCnpjs": [],
  "procurementMethods": [],
  "daysBack": 3,
  "daysAhead": 30,
  "dateFrom": "",
  "dateTo": "",
  "maxItems": 20,
  "maxApiRequests": 40,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `records` (type: `string`):

One row per PNCP tender (contratação) or contract, with English labels next to the Portuguese ones and the PNCP source credit (source, sourceUrl, license, retrievedAt) on every item.

# 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 = {
    "mode": "published",
    "keywords": [],
    "states": [],
    "cities": [],
    "buyerCnpjs": [],
    "procurementMethods": [],
    "daysBack": 3,
    "daysAhead": 30,
    "dateFrom": "",
    "dateTo": "",
    "maxItems": 20,
    "maxApiRequests": 40,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("jpopendata/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 = {
    "mode": "published",
    "keywords": [],
    "states": [],
    "cities": [],
    "buyerCnpjs": [],
    "procurementMethods": [],
    "daysBack": 3,
    "daysAhead": 30,
    "dateFrom": "",
    "dateTo": "",
    "maxItems": 20,
    "maxApiRequests": 40,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("jpopendata/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 '{
  "mode": "published",
  "keywords": [],
  "states": [],
  "cities": [],
  "buyerCnpjs": [],
  "procurementMethods": [],
  "daysBack": 3,
  "daysAhead": 30,
  "dateFrom": "",
  "dateTo": "",
  "maxItems": 20,
  "maxApiRequests": 40,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call jpopendata/brazil-pncp-tenders --silent --output-dataset

```

## MCP server setup

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