# Poland Company Registry — KRS/REGON Official API (`bovi/poland-company-registry`) Actor

Look up Polish companies by KRS number via the official Ministry of Justice KRS API — free, no key. Returns legal name, form, status, address, PKD activity codes, board/representation. Optional REGON (GUS) enrichment resolves NIP/REGON with your own free GUS key.

- **URL**: https://apify.com/bovi/poland-company-registry.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Business, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 poland company registry — krs/regon official apis

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Poland Company Registry Scraper — Official KRS/REGON APIs

Used by KYC analysts, M\&A associates, and B2B sales teams who need live Polish company status, board members, and PKD activity codes without managing a KRS/REGON integration themselves.

Look up Polish companies via the official **KRS** (Krajowy Rejestr Sądowy — National Court Register) API — completely free, **no key or signup required**. Returns legal name, form, status, registered address, PKD activity codes, and board/representation. Optional **REGON** (GUS statistical register) enrichment resolves NIP/tax-ID numbers to full records, using your own free GUS key. Pay per result.

**$4.50/1K records** (Pay Per Event). First 10 results free. No proxy needed. No scraping ban risk. Government data source — authoritative, directly from the Ministry of Justice's KRS API.

### Two data sources, two different access models

| | KRS | REGON |
|---|---|---|
| Runs | Ministry of Justice | GUS (Central Statistical Office) |
| Auth | **None** — fully open API | Free key, but **not instant self-serve** |
| Lookup by | KRS number only (exact) | NIP, REGON, or KRS number |
| Search by company name | ❌ Not available on this API | ❌ Not available |
| Data richness | Rich: legal form, address, PKD codes, board/representation | Identity + address only |

**If you already have a KRS number** (10 digits, e.g. `0000023302`), you need nothing else — just `krsNumbers` and you're done, free.

**If you only have a NIP (tax ID) or REGON number**, KRS's own API has no way to resolve that — you need REGON, and REGON needs a key from GUS (see below).

### Getting your REGON API key (only needed for `nipNumbers` / `regonNumbers`)

Unlike Companies House's instant web-form key, GUS does **not** offer self-serve production access:

1. Email `regon_bir@stat.gov.pl` with: your entity name, your own REGON, a contact person, and the IP address(es) your requests will come from (Apify runs use rotating cloud IPs — check with GUS how they want this handled, or run this actor from a fixed proxy/IP if they require it).
2. GUS says turnaround is "coordinated individually" — there's no published SLA. Budget a few business days.
3. Once issued, paste the key into `regonApiKey`.

**To test the integration without waiting on GUS**, tick `useRegonTestEnv` — this uses GUS's public sandbox key against a frozen, address-anonymized database snapshot from 2014. It proves the plumbing works; it will not return current real-world matches.

If you don't need NIP/REGON search, skip all of this — `krsNumbers` mode needs zero setup.

### What you get

| Field | Description |
|---|---|
| `krs_number` | KRS registration number (e.g. `0000023302`) |
| `nip` | Tax ID (10 digits) |
| `regon` | Statistical register ID (9 or 14 digits) |
| `registry_type` | `P` (companies) or `S` (associations) |
| `name` | Full legal name |
| `legal_form` | e.g. `SPÓŁKA AKCYJNA`, `SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ` |
| `status` | `active`, `in_liquidation`, `bankruptcy`, `merged_or_transformed`, `terminated` (see note below) |
| `registration_date` | Date first entered into KRS |
| `last_entry_date` | Date of the most recent register entry |
| `address_line_1` / `address_line_2` | Street + house/flat number |
| `locality` | City/town |
| `voivodeship` | Region (województwo) |
| `postal_code` | Postal code |
| `country` | Country |
| `website` | Company website, when filed |
| `pkd_main_code` / `pkd_main_description` | Primary business activity (Polish Classification of Activities) |
| `pkd_codes` | List of secondary activity codes/descriptions |
| `representation_method` | How the entity can legally bind itself (e.g. "two board members jointly") |
| `board_members` / `board_members_count` | Current board/officers — `[{name, function, suspended}]` |
| `registry_court` | Court/authority behind the last register entry |
| `source` | `krs` or `regon` — which API produced this row |
| `query` | The input value (KRS/NIP/REGON) that produced this record |
| `parse_confidence` | Data quality score 0–1 |
| `warnings` | Machine-readable quality flags |

**Privacy note:** board members' PESEL (Polish national ID number) is never surfaced in the output, even masked — the government API itself already returns it pre-masked (e.g. `6**********`), and we drop it entirely rather than pass through a partial identifier.

### A note on `status`

Unlike UK Companies House, the KRS API has **no simple active/dissolved field**. We derive `status` from which register sections (dzial6 — mergers/liquidation/bankruptcy) are present on the entry:

- `active` — no liquidation/bankruptcy/merger section present.
- `in_liquidation` — entity is in formal liquidation.
- `bankruptcy` — bankruptcy proceedings are on file.
- `merged_or_transformed` — entity merged into / was absorbed by / transformed from another entity (common for banks/holding restructures — the entity may still be legally active).
- `terminated` — REGON-sourced records only, when `DataZakonczeniaDzialalnosci` (activity end date) is set.

This is an honest best-effort heuristic, documented here and in `src/normalize.py`. For hard compliance decisions, read `registry_court` / `last_entry_date` alongside `status`, or pull `fullExtract: true` for the complete historical record.

### Modes

**KRS direct lookup (free, default)** — provide `krsNumbers` (e.g. `["0000023302", "0000025237"]`). One record per number. Set `registryType` to `S` for associations/foundations, or `auto` to try both.

**REGON enrichment (optional, needs your own key)** — provide `nipNumbers` and/or `regonNumbers` plus `regonApiKey`. Each match returns identity + address (no board/PKD — those are KRS-only fields, left `null` on REGON-sourced rows, distinguishable via `source: "regon"`).

**Both together** — combine any of the four list inputs in one run.

### Use cases

- **KYC / due diligence** — verify Polish counterparty legal status, registration, and board
- **B2B lead generation** — enrich a list of Polish company names/NIPs with registry data
- **Compliance screening** — identify liquidated, bankrupt, or merged entities
- **Beneficial ownership research** — extract board/representation structures
- **Market research** — map PKD activity codes across a sector

### Data sources

- **KRS** — Krajowy Rejestr Sądowy, the official Polish court register of companies/associations, maintained by the Ministry of Justice (Ministerstwo Sprawiedliwości). https://prs.ms.gov.pl/krs/openApi
- **REGON** — the statistical business register (Baza Internetowa REGON, BIR1.1), maintained by GUS (Główny Urząd Statystyczny). https://api.stat.gov.pl/Home/RegonApi

### Pricing

**Pay-per-result (PPE):**

| Event | Rate | Trigger |
|---|---|---|
| `company-record` | **$4.50/1K** | Every company record returned, from either source |

No monthly subscription. No officer/board add-on fee — board data is included free whenever KRS returns it.

**Worked examples:**

| Run | Records | Cost |
|---|---|---|
| 100 KRS lookups | 100 | **$0.45** |
| 1,000 KRS lookups | 1,000 | **$4.50** |
| 500 NIP lookups via REGON | 500 | **$2.25** |

### FAQ

**Do I need a proxy or API key?**
For `krsNumbers` lookups: no, nothing at all — the KRS API is fully open. For `nipNumbers`/`regonNumbers`: you need your own free REGON key from GUS (see "Getting your REGON API key" above — it's not instant).

**Can I search by company name?**
Not on either official API — neither KRS nor REGON's `DaneSzukajPodmioty` supports free-text name search. You need a KRS number, NIP, or REGON number to start. If you only have a name, look it up once at wyszukiwarka-krs.ms.gov.pl (the Ministry's own portal, not part of this API) to get the KRS number, then feed that number to this actor for structured, repeatable, machine-readable data.

**What if a KRS number doesn't exist?**
The API returns HTTP 404; that lookup is skipped and reported in the run's `failedDetails`, and it is not charged.

**What output formats are available?**
JSON, CSV, and Excel — all via the Apify dataset.

### Notes

- The KRS API is genuinely keyless and unauthenticated — verified live against `https://api-krs.ms.gov.pl` (2026-07-14).
- The REGON API is SOAP (BIR1.1), not REST — this actor handles the SOAP/WS-Addressing plumbing internally via `zeep`; you only ever provide a key.
- `parse_confidence` is 1.0 for records with a valid KRS/REGON number and name; it deducts for missing address, missing PKD, or fully empty responses.
- REGON's search-result field names in `src/regon_client.py` are documented from GUS's official technical instruction plus cross-referenced against independent open-source REGON clients; they could not be validated against a *populated* production response during development (only the empty 2014 test sandbox was reachable without a production key). Every field read is defensive — an unexpected field name degrades to `null` + a warning, never a crash. Run `scripts/probe.py` with a real production key to validate against live data before a large run.
- Live validation: run `python3 scripts/probe.py` (KRS, no key needed) or `python3 scripts/probe.py --regon-test` (REGON sandbox) to verify the integration end-to-end.

### vs. Competitors

| Feature | This Actor | HTML-scraping KRS actors (Store) | Paid KYC APIs |
|---|---|---|---|
| Data source | Official KRS REST API + optional REGON SOAP API | HTML scraping wyszukiwarka-krs.ms.gov.pl | Third-party aggregator |
| Proxy needed | No | Yes ($$$) — the portal is bot-protected (verified: returns HTTP 403 to direct requests) | No, but paid per call |
| Board/representation | Yes (from KRS dzial2) | Partial/unreliable | Varies |
| PKD activity codes | Yes (main + secondary) | Partial | Varies |
| parse\_confidence | Yes | No | No |
| Cost | **$4.50/1K** | Similar + proxy COGS | Usually $10-30+/1K |

### Use with AI agents (MCP)

An agent calls this tool to **look up Polish company registration status, address, PKD codes, and board members mid-conversation** — e.g. "is KGHM Polska Miedź still active?", "who's on the board of KRS 0000023302?", or "resolve this NIP to a company name."

Point your MCP client at this tool:

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://mcp.apify.com/?tools=bovi/poland-company-registry",
        "--header",
        "Authorization: Bearer <YOUR_APIFY_TOKEN>"
      ]
    }
  }
}
```

Minimal agent input (KRS lookup, no key needed):

```json
{
  "krsNumbers": ["0000023302"]
}
```

With REGON enrichment (requires your own GUS key):

```json
{
  "nipNumbers": ["7342867148"],
  "regonApiKey": "<YOUR_REGON_API_KEY>"
}
```

Example output row an agent can reason over directly:

```json
{
  "krs_number": "0000023302",
  "nip": "6920000013",
  "regon": "39002176400000",
  "name": "KGHM POLSKA MIEDŹ SPÓŁKA AKCYJNA",
  "legal_form": "SPÓŁKA AKCYJNA",
  "status": "active",
  "registration_date": "29.06.2001",
  "locality": "LUBIN",
  "postal_code": "59-301",
  "voivodeship": "DOLNOŚLĄSKIE",
  "pkd_main_code": "07.29.Z",
  "pkd_main_description": "GÓRNICTWO POZOSTAŁYCH RUD METALI NIEŻELAZNYCH",
  "board_members_count": 5,
  "source": "krs",
  "parse_confidence": 1.0,
  "warnings": []
}
```

Reliability for agents: KRS data comes from the **official Polish Ministry of Justice API** (not HTML scraping), so results don't break on website redesigns. Every record includes a stable `krs_number` and/or `regon`/`nip` for de-duplication and joining across runs. Data quality is tracked via `parse_confidence` and machine-readable `warnings`.

### Integrations

Built for KYC analysts, M\&A associates, and B2B sales teams enriching Polish company status, board members, and PKD codes — the JSON/dataset output drops into the tools you already run, no glue code:

- **n8n / Make / Zapier** — trigger a run or pipe every new dataset item into 500+ apps (Google Sheets, Airtable, Slack, HubSpot, your database) with no code: [n8n](https://docs.apify.com/platform/integrations/n8n), [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier).
- **Webhooks** — fire your own endpoint the moment a run finishes, to push results straight into your pipeline ([docs](https://docs.apify.com/platform/integrations/webhooks)).
- **MCP server** — expose this actor as a tool to Claude, Cursor, or any [MCP client](https://mcp.apify.com) so an AI agent can pull this data mid-conversation ([guide](https://blog.apify.com/how-to-use-mcp/)).
- **API & SDKs** — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.

See all [Apify integrations](https://apify.com/integrations).

### More scrapers from our toolkit

Building a data pipeline? These pair well with this one — each runs on your own Apify account with the same pay-per-result pricing, no subscription:

- [UK Companies House Scraper](https://apify.com/bovi/companies-house-uk)
- [Companies France](https://apify.com/bovi/companies-france)

# Actor input Schema

## `krsNumbers` (type: `array`):

Krajowy Rejestr Sądowy registration numbers, 10 digits (e.g. '0000023302' for KGHM Polska Miedź). No API key needed — the KRS API is open. Returns one full company record per number, including legal form, status, address, PKD activity codes, and board/representation.

## `registryType` (type: `string`):

Which KRS sub-register to search. 'P' = Rejestr Przedsiębiorców (companies — the default, correct choice for almost all business lookups). 'S' = Rejestr Stowarzyszeń (associations/foundations/NGOs). 'auto' tries P first, then falls back to S — costs one extra API call per miss, use only if you're not sure which register a number belongs to.

## `fullExtract` (type: `boolean`):

When true, fetches OdpisPelny (full extract, includes the complete historical change log) instead of OdpisAktualny (current-state extract, default). Full extracts are larger and rarely needed — leave off unless you specifically need past board members, past addresses, or past PKD codes.

## `regonApiKey` (type: `string`):

Free key from GUS (Polish Central Statistical Office), required ONLY if you use nipNumbers or regonNumbers below. Unlike the KRS API, this is NOT instant self-serve — you email regon\_bir@stat.gov.pl with your details and IP address; GUS issues the key manually (see README 'Getting your REGON API key'). Leave blank if you only need krsNumbers lookups.

## `nipNumbers` (type: `array`):

Polish tax identification numbers (NIP, 10 digits) to resolve via the REGON API. Requires regonApiKey. The KRS API itself has no NIP search — this is the only free official path from 'I have a NIP' to company data.

## `regonNumbers` (type: `array`):

REGON statistical register numbers (9 or 14 digits) to look up directly via the REGON API. Requires regonApiKey.

## `useRegonTestEnv` (type: `boolean`):

For evaluation only. Routes REGON calls to GUS's public test sandbox (works with the well-known test key without any signup) instead of production. The sandbox database is a frozen, address-anonymized snapshot from 2014 — fine for verifying the integration works, not useful for real lookups. Leave off for real runs.

## Actor input object example

```json
{
  "krsNumbers": [
    "0000023302",
    "0000025237"
  ],
  "registryType": "P",
  "fullExtract": false,
  "useRegonTestEnv": false
}
```

# Actor output Schema

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

Dataset containing Poland Company Registry records (krs\_number, nip, regon, name, legal\_form, status, registration\_date, locality, postal\_code, voivodeship, pkd\_main\_description, board\_members\_count, source, parse\_confidence).

# 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 = {
    "krsNumbers": [
        "0000023302",
        "0000025237"
    ],
    "registryType": "P"
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/poland-company-registry").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 = {
    "krsNumbers": [
        "0000023302",
        "0000025237",
    ],
    "registryType": "P",
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/poland-company-registry").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 '{
  "krsNumbers": [
    "0000023302",
    "0000025237"
  ],
  "registryType": "P"
}' |
apify call bovi/poland-company-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/poland-company-registry"
        }
    }
}

```

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/A5Ste6PsOe6v2qDZx/builds/t8nBWj8dPoHt2TTet/openapi.json
