# Poland Building Permits API – Official GUNB RWDZ (`enterprising_hamster/polish-building-permits-gunb`) Actor

Poland building permits and construction notifications from the official GUNB register (RWDZ): project, category, cubature, location, dates, office. Investor, address and plots for companies and public bodies; private persons anonymised. Filter by region, date, category. Export CSV, JSON or Excel.

- **URL**: https://apify.com/enterprising_hamster/polish-building-permits-gunb.md
- **Developed by:** [Kamil Kaczmarek](https://apify.com/enterprising_hamster) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 projects

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

## Poland Building Permits API – Official GUNB Register

**Poland building permits API**: new **building permits** and **construction notifications** from all of Poland, straight from the official register of the Chief Building Control Office (GUNB): **RWDZ, Rejestr Wniosków, Decyzji i Zgłoszeń w sprawach budowlanych**. For each case you get the project name, building category (I–XXX), type of works, cubature, commune with TERYT codes, application and decision dates and the issuing office. When the investor is a **company, public body, church, non-profit or housing community** you also get its name, the site address, case and decision numbers and the plots with parcel IDs ready for ULDK and maps. Filter by voivodeship, county or commune, date, category, investor type or keywords, newest first, and export JSON, CSV or Excel. Polski opis: **pozwolenia na budowę** i zgłoszenia robót budowlanych z rejestru RWDZ GUNB, z filtrem regionu i daty; osoby fizyczne zanonimizowane.

**No private persons.** Investors who are people, sole traders or partnerships are never named, and their cases come at commune level only: no address, plots, case numbers or a project name that could point at them. Designers are never published. See [Privacy](#privacy).

### What data can you get

Permit decisions and notifications without objection registered since 2016, refreshed every night by GUNB. Mazowieckie alone has about 400,000 permit cases; notifications for the whole country add about 390,000.

- **Project:** name (nazwa zamierzenia), building category with English and Polish names, investment kind (single-family house or other), type of works (new build, extension, superstructure, reconstruction, demolition, other), cubature in m³.
- **Dates and status:** application date, permit decision date, notification status (no objection).
- **Where:** TERYT codes of commune, county and voivodeship for every case; for named investors also street, house number, city and plots (`parcelId` such as `146501_8.0101.AR_2.12/3`, the ULDK format).
- **Who:** investor name and type (COMPANY, PUBLIC, RELIGIOUS, NON_PROFIT, HOUSING_COMMUNITY); the issuing office and its address.
- **Identifiers:** a stable `recordId`, and for named investors the GUNB case number, office case number and decision number.

### How to use

1. Press **Start**. With no changes you get the 100 newest permits in Mazowieckie (under a minute).
2. Pick **voivodeships** (or *Whole country*) or **TERYT codes** of counties and communes, then narrow by **date**, **building category**, **type of works**, **investor type** or **keywords**.
3. Tick **Only cases with a named investor** for B2B leads: developers, logistics parks, public tenders in preparation.
4. Schedule a daily run with **Only new or changed cases** to get a feed of fresh permits.

### Input

Company/public permits in Warsaw from the last 30 days (B2B leads):

```json
{ "terytCodes": ["1465"], "onlyWithInvestor": true, "daysBack": 30, "maxItems": 100 }
```

New warehouses and factories ≥10,000 m³ anywhere in Poland in the last 90 days (market / sales):

```json
{ "voivodeships": ["ALL"], "categories": ["XVIII"], "worksTypes": ["NEW_BUILD"], "minCubature": 10000, "daysBack": 90, "maxItems": 500 }
```

| Field | Default | What it does |
|---|---|---|
| `registers` | `["PERMITS"]` | `PERMITS` (building permit decisions) and/or `NOTIFICATIONS` (zgłoszenia, no investor column). |
| `voivodeships` | `["14"]` Mazowieckie | TERYT codes `02`-`32` or names such as `małopolskie`; `["ALL"]` for the whole country. |
| `terytCodes` | none | County or commune prefixes, e.g. `1465` Warsaw, `1261` Kraków. When set, they replace `voivodeships`. |
| `dateFrom`, `dateTo`, `daysBack` | none | Decision date for permits, application date for notifications. |
| `categories` | all | Roman numerals `I`-`XXX`, e.g. `XVIII` industrial and warehouse buildings, `XIII` multi-family housing. |
| `investmentKinds` | all | `SINGLE_FAMILY_HOUSE`, `OTHER`. |
| `worksTypes` | all | `NEW_BUILD`, `EXTENSION`, `SUPERSTRUCTURE`, `RECONSTRUCTION`, `DEMOLITION`, `OTHER_WORKS`, `UNKNOWN`. |
| `onlyWithInvestor` | `false` | Only permits with a named organisation investor. |
| `investorTypes` | any | `COMPANY`, `PUBLIC`, `RELIGIOUS`, `NON_PROFIT`, `HOUSING_COMMUNITY`. |
| `investorContains` | none | Text in the investor name, e.g. `Dom Development`. |
| `keywords` | none | Any of these words in the project name, e.g. `hala`, `fotowolta`. |
| `minCubature` | `0` | Minimum cubature in m³. |
| `maxItems` | `100` | Newest first; hard cap of results and cost. |
| `onlyNew`, `stateKey` | `false`, `default` | Skip cases delivered earlier with unchanged data. |

### Output

A permit with a named investor (shortened):

```json
{
  "recordId": "RWDZ-CBCA84C2525D3716",
  "register": "PERMIT",
  "investorDisclosed": true,
  "investorName": "Zakład Komunalny Sp. z o.o.",
  "investorType": "COMPANY",
  "projectName": "Budowa instalacji termicznego przekształcenia odpadów wraz z odzyskiem energii",
  "worksType": "OTHER_WORKS",
  "categoryCode": "XVIII",
  "categoryName": "industrial and warehouse buildings",
  "applicationDate": "2026-08-04",
  "decisionDate": "2026-10-09",
  "status": "DECISION_ISSUED",
  "caseNumber": "ST-OP-OP/WNIOSEK/4474/2026",
  "decisionNumber": "374/2026",
  "locationPrecision": "ADDRESS",
  "street": "ul. Podmiejska",
  "houseNumber": "69",
  "city": "Opole",
  "terytCode": "1661011",
  "voivodeship": "opolskie",
  "parcels": [{"parcelId": "166101_1.0058.24", "unit": "166101_1", "precinct": "0058", "number": "24", "sheet": null}],
  "parcelsCount": 2,
  "authorityName": "Prezydent Miasta Opole",
  "license": "CC0 1.0 (dane.gov.pl). Source: Główny Urząd Nadzoru Budowlanego, RWDZ; processed by this Actor, people's data removed."
}
```

A private person's permit has `investorDisclosed: false`, `locationPrecision: "COMMUNE"`, the TERYT codes, category, dates, cubature and office, and nulls for investor, address, plots and numbers. The run's key-value store also holds `SUMMARY` (files read, matching cases, cases with a named investor, withheld project names) and `RUN_STATS`.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `project` | $0.002 | One delivered case without a named investor (private person, or a notification). |
| `project-with-investor` | $0.006 | One delivered permit with a named organisation investor, address, plots and numbers. |

100 newest Mazowieckie permits cost about $0.30 (roughly a fifth have a named investor). US building permit Actors in the Apify Store charge $0.002-0.01 per permit and UK planning applications $0.01-0.02. A case delivered once is never charged again in the same run, and **Only new or changed cases** keeps scheduled runs cheap.

### Use cases

- **Construction sales:** materials, windows, HVAC, PV, elevators and general contractors find projects at the permit stage.
- **Developers and real estate:** competitors' new projects and land use by county.
- **Market analysis:** permits by category, commune and month; housing pipeline.
- **Public sector:** schools, roads and networks permitted to communes before tenders appear.
- **Monitoring:** a daily feed of new permits in chosen counties.

### Privacy

The register is public under Art. 82b of the Construction Law, which excludes the investor's address from publication, and GDPR still applies to personal data in public registers (judgment of the Supreme Administrative Court, III OSK 2357/22). This Actor therefore:

- **Names** only investors whose name carries a legal form or public-body marker (sp. z o.o., S.A., gmina, powiat, parafia, fundacja, wspólnota mieszkaniowa…) and no first name with a surname (checked against the PESEL first-name list).
- **Does not name** people, sole traders, civil, general or professional partnerships, or limited partnerships without a company general partner. Their cases come without investor, street, house number, city, postal code, plots, case, office and decision numbers; `recordId` is a hash, not the case number.
- **Withholds** the project name of such cases when it contains a digit, an address word or a proper noun after the first word, and any project name that contains a person's name.
- **Never reads** the designer columns.

Use the data for business-to-business contact with organisations and follow GDPR when you contact anyone.

### FAQ

**Is there an API for building permits in Poland?** GUNB publishes RWDZ as open data (CSV downloads, nightly refresh) and has APIs aimed at local building offices (e-Budownictwo). This Actor turns the public RWDZ files into one filterable table callable from the Apify API, with CSV/JSON/Excel export.

**How do I export Polish building permits to CSV or Excel?** Set Max items (and region/date filters), run the Actor, then download the dataset as CSV or Excel from the run page or via the Apify API.

**Can I get the investor name and plot IDs?** Yes for organisation investors (companies, public bodies, churches, non-profits, housing communities): name, address, case/decision numbers and `parcelId` in ULDK format. Private persons, sole traders and partnerships stay anonymised at commune level only.

**Does it cover the whole country?** Yes — pick voivodeships or `["ALL"]`, or TERYT codes for counties/communes. Default is the 100 newest permits in Mazowieckie so a cold start stays cheap and fast.

**Is this legal?** GUNB publishes the register as open data on dane.gov.pl (dataset 3467) under **CC0 1.0**, with no account needed; `robots.txt` allows the download folder. Crediting the source is not required by CC0 but is kept in `source` and `license`.

**Does the permit say whether it was granted?** The open data lists issued decisions without their outcome; every permit row has a decision number and date. Notifications carry their status (no objection).

**Why is there no investor for notifications?** GUNB does not publish it in the notifications file.

**How do I filter by city?** Use TERYT codes: `1465` Warsaw, `1261` Kraków, `0264` Wrocław, `3064` Poznań, `2261` Gdańsk, `1061` Łódź.

**How fresh is it?** GUNB regenerates the files every night. Offices enter cases with a delay, especially notifications, so the last few days fill in over the following weeks; with **Only new or changed cases** late entries still reach you.

**How long does a run take?** One voivodeship takes about 1-2 minutes. The whole country means 16 files (about 350 MB) and takes several minutes; give the run more memory (2-4 GB) for more CPU and a faster run. Date and category filters make reading faster.

### Integrations

Call the Actor from the Apify API, Python or JavaScript clients, Make, Zapier, n8n or the Apify MCP server and read the dataset as JSON, CSV or Excel. Pair `parcelId` with a ULDK Actor to get plot geometry and zoning.

### Development

```bash
python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q
examples/run-local-ppe.sh examples/warsaw-company-permits.json
```

### Disclaimer

Data comes from the Rejestr Wniosków, Decyzji i Zgłoszeń w sprawach budowlanych (RWDZ) kept by the Główny Urząd Nadzoru Budowlanego, published at wyszukiwarka.gunb.gov.pl and on dane.gov.pl (dataset 3467) under CC0 1.0, processed by this Actor (filtered, grouped by case, translated codes, people's data removed). Not an official extract. The first-name list used for privacy screening comes from the PESEL register (dane.gov.pl dataset 1667, CC0 1.0).

### 🇵🇱 Po polsku

Aktor zwraca pozwolenia na budowę i zgłoszenia robót budowlanych z Rejestru Wniosków, Decyzji i Zgłoszeń (RWDZ) Głównego Urzędu Nadzoru Budowlanego: nazwę zamierzenia, kategorię obiektu (I-XXX), rodzaj robót, kubaturę, gminę z kodami TERYT, daty wniosku i decyzji oraz organ. Gdy inwestorem jest spółka, jednostka samorządu lub inny organ publiczny, kościół, fundacja, stowarzyszenie, spółdzielnia lub wspólnota mieszkaniowa, także nazwę inwestora, adres budowy, numery sprawy i decyzji oraz działki z identyfikatorem w formacie ULDK. Filtry: województwo, powiat lub gmina (TERYT), daty, kategoria, rodzaj inwestycji i robót, typ inwestora, fragment nazwy inwestora, słowa w nazwie zamierzenia, minimalna kubatura; najnowsze najpierw. Osoby fizyczne, jednoosobowe działalności i spółki osobowe nie są wymieniane z nazwy, a ich sprawy są podawane tylko z dokładnością do gminy, bez adresu, działek i numerów. Dane projektantów nie są odczytywane. Źródło: RWDZ, GUNB, dane.gov.pl, licencja CC0 1.0.

# Changelog

This Actor's version history is a separate document: https://apify.com/enterprising_hamster/polish-building-permits-gunb/changelog.md

# Actor input Schema

## `registers` (type: `array`):

PERMITS = building permit decisions (pozwolenia na budowę, with the investor where it is an organisation). NOTIFICATIONS = construction notifications without objection (zgłoszenia, whole country, no investor column). Empty = PERMITS.

## `voivodeships` (type: `array`):

Regions to read. Not set = mazowieckie, so the first run is quick. Choose 'Whole country' for all 16. Ignored when TERYT codes are given.

## `terytCodes` (type: `array`):

TERYT code prefixes: 2 digits for a voivodeship, 4 for a county (1465 = Warsaw, 1261 = Kraków, 3064 = Poznań, 0264 = Wrocław), 6-7 for a commune. When set, these replace the voivodeship list.

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

Earliest decision date (permits) or application date (notifications).

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

Latest decision date (permits) or application date (notifications).

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

Only cases from the last N days (0 = no limit). Combined with 'From date', the later date wins.

## `categories` (type: `array`):

Construction Law categories. Empty = all.

## `investmentKinds` (type: `array`):

Single-family house or anything else. Empty = both.

## `worksTypes` (type: `array`):

Empty = all.

## `onlyWithInvestor` (type: `boolean`):

Only permits whose investor is a company, public body, church, non-profit or housing community (named, with address and plots). Cases of private individuals are never named.

## `investorTypes` (type: `array`):

Only permits whose investor is of these types (implies a named investor). Empty = any.

## `investorContains` (type: `string`):

Text in the investor name, e.g. 'Dom Development' or 'Gmina'. Case and Polish letters do not matter. Implies a named investor.

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

Any of these words in the project name, e.g. 'hala', 'magazyn', 'fotowolta'. Case and Polish letters do not matter.

## `minCubature` (type: `integer`):

Only projects at least this large (cubature as stated in the register; many entries have none).

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

Newest first. You pay per delivered result.

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

Skip cases delivered by an earlier run with the same state key and unchanged since. Use with a schedule to get a daily feed of new permits.

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

Name of the memory used by 'Only new or changed cases'. Use one key per monitored search.

## Actor input object example

```json
{
  "registers": [
    "PERMITS"
  ],
  "voivodeships": [
    "14"
  ],
  "onlyWithInvestor": false,
  "maxItems": 100,
  "onlyNew": false
}
```

# Actor output Schema

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

One item per permit or notification case, newest first.

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

Files read, matching cases, cases with a named investor, withheld project names and charge limit.

# 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 = {
    "registers": [
        "PERMITS"
    ],
    "voivodeships": [
        "14"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("enterprising_hamster/polish-building-permits-gunb").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 = {
    "registers": ["PERMITS"],
    "voivodeships": ["14"],
}

# Run the Actor and wait for it to finish
run = client.actor("enterprising_hamster/polish-building-permits-gunb").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 '{
  "registers": [
    "PERMITS"
  ],
  "voivodeships": [
    "14"
  ]
}' |
apify call enterprising_hamster/polish-building-permits-gunb --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,enterprising_hamster/polish-building-permits-gunb"
        }
    }
}
```

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/oKeF1ra1yOghBMskc/builds/W1ZfWG6BBKb3sCsJE/openapi.json
