# Poland Company Lookup API – REGON, NIP, KRS (`enterprising_hamster/polish-company-lookup-regon`) Actor

Look up a Polish company by NIP, REGON or KRS in the official GUS REGON register: name, address, PKD, dates and optional VAT status. No phone, fax or email. For KYC, CRM and AI agents (MCP).

- **URL**: https://apify.com/enterprising_hamster/polish-company-lookup-regon.md
- **Developed by:** [Kamil Kaczmarek](https://apify.com/enterprising_hamster) (community)
- **Categories:** Lead generation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 companies

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 Company Lookup API – REGON, NIP, KRS

**Poland company lookup API** for the official **REGON API** (GUS BIR1.2). **NIP lookup**, REGON lookup and KRS lookup each return one row of **Polish company data**: registered name, identifiers, seat, PKD, dates and, optionally, VAT status. Press Start, no GUS key needed, and export CSV, JSON or Excel. Polski opis jest na dole strony.

The default input is five large organisations, so a first run stays short. A subject that GUS does not know is returned with `found: false` and is not charged.

### Use with AI agents (MCP)

Agents can call this Actor through the [Apify MCP server](https://mcp.apify.com). Add it as a single tool:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=enterprising_hamster/polish-company-lookup-regon"
    }
  }
}
```

Questions an agent can answer with it:

- "Look up this Polish NIP." → `{"nips": ["7740001454"]}`
- "REGON and PKD for these suppliers, plus VAT status." → `{"nips": ["6920000013", "5250007738"], "checkVatStatus": true}`
- "Which company has KRS 0000026438?" → `{"krsNumbers": ["0000026438"]}`

Fields an agent gets: `name`, `regon`, `nip`, `krs`, `entityType`, `legalForm`, `address`, `prevailingPkd`, `otherPkd`, `status`, `vatStatus`.

Cost per result: $0.003 per delivered company. Higher Apify plans pay less per row. Pass `maxTotalChargeUsd` in the MCP `callOptions`; the run stops before that limit and still returns SUCCEEDED with the rows saved so far.

### What data

For each NIP, REGON or KRS the Actor searches the official REGON register and reads the BIR1.2 full report for that type of subject:

- **Identity:** registered name, 9- or 14-digit REGON, NIP, KRS when the registry entry is KRS, entity type (`legal_person`, `sole_trader`, `local_unit`).
- **Form:** basic and specific legal form, ownership form, registry authority and register name.
- **Seat:** voivodeship, county, municipality, city, postal code, TERYT symbols. Street, building and apartment for legal persons. For a sole trader those three lines are omitted unless you ask for them.
- **Activity:** prevailing PKD and the other PKD codes, with classification version `2007` or `2025`, plus status `active`, `suspended` or `closed` derived from the register dates.
- **Dates:** start, REGON registration, suspension, resumption, end, deletion, last change.
- **Website:** legal persons only, when REGON stores one.
- **VAT:** optional status `Czynny`, `Zwolniony` or `Niezarejestrowany` from the Ministry of Finance WL2 method, with the check time and request id.
- **Local units:** optional, nested, at most 50, no extra charge.

`environment` is `production` or `test`. `source` is always `GUS REGON BIR1.2`. `retrievedAt` is when the row was built. `sourceUrl` points at the official REGON search page.

### How to use

1. Nothing to set up: the Actor queries production GUS data with its own BIR1 key. Your own key in **GUS API key** is optional.
2. Paste NIPs, REGONs, KRS numbers, or a mixed list with prefixes `NIP:`, `REGON:` and `KRS:`.
3. Press **Start**. With the default identifiers you get those organisations.
4. Turn on **Check VAT status** when you need the taxpayer status before a payment. Turn on **Include local units** for branches. Turn off **Include sole traders** to skip JDG without a charge.
5. Set **Max companies** or an Apify max charge. The run stops before the charge limit and keeps the rows already saved.

### Input

| Field | Meaning |
| --- | --- |
| `nips` | NIP numbers. Spaces, hyphens and a leading `PL` are ignored. |
| `regons` | 9-digit subjects or 14-digit local units. |
| `krsNumbers` | KRS numbers, zero-padded to 10 digits. Looked up one at a time. |
| `identifiers` | Mixed list. Prefixes `NIP:`, `REGON:`, `KRS:`. Without a prefix, 9 or 14 digits are a REGON and 10 digits with a valid NIP checksum are a NIP. Anything else is `ambiguous, use prefix`. |
| `gusApiKey` | Optional production BIR1 key of your own. Secret. Leave empty to use the Actor's key. |
| `useTestEnvironment` | Public GUS test service, used only when no key is available (self-hosted runs). Default **false**. |
| `includeLocalUnits` | Nest up to 50 local units. Default **false**. |
| `includeSoleTraders` | Default **true**. When false, a sole trader is `skipped: "sole_trader"` and is not charged. |
| `soleTraderFullAddress` | Street, building and apartment for a sole trader. Default **false**. |
| `checkVatStatus` | WL2 VAT status. Default **false**. |
| `maxItems` | Cap on charged companies. Empty means no cap. |

Duplicates across the four lists are collapsed. Up to 20 NIPs or REGONs go in one GUS search. Several identifiers that resolve to the same REGON are charged once per run.

### Output

One item per subject. Example from the GUS test environment (other PKD codes trimmed). Streets in that environment are anonymized:

```json
{
  "name": "POLSKI KONCERN NAFTOWY ORLEN SPÓŁKA AKCYJNA",
  "regon": "610188201",
  "nip": "7740001454",
  "krs": "0000028860",
  "entityType": "legal_person",
  "legalForm": {
    "basic": {"code": "1", "name": "OSOBA PRAWNA"},
    "specific": {"code": "116", "name": "SPÓŁKI AKCYJNE"}
  },
  "address": {
    "voivodeship": "MAZOWIECKIE",
    "county": "m. Płock",
    "municipality": "M. Płock",
    "city": "Płock",
    "postalCode": "09411",
    "street": "ul. Test-Wilcza",
    "buildingNumber": "7",
    "apartmentNumber": null
  },
  "prevailingPkd": {
    "code": "1920Z",
    "name": "WYTWARZANIE I PRZETWARZANIE PRODUKTÓW RAFINACJI ROPY NAFTOWEJ"
  },
  "otherPkd": [
    {"code": "5813Z", "name": "WYDAWANIE GAZET"}
  ],
  "pkdVersion": "2007",
  "status": "active",
  "startDate": "1993-07-01",
  "registrationDate": null,
  "vatStatus": null,
  "vatCheckedAt": null,
  "vatRequestId": null,
  "vatError": null,
  "environment": "test",
  "source": "GUS REGON BIR1.2",
  "sourceUrl": "https://wyszukiwarkaregon.stat.gov.pl/appBIR/index.aspx",
  "found": true,
  "error": null,
  "skipped": null
}
```

`examples/sample-item.json` is that same test-environment subject with every field. The table view **Companies** shows name, REGON, NIP, KRS, type, status, city and prevailing PKD. The key-value record **SUMMARY** holds saved, found, not found, invalid, skipped sole traders, seen duplicates, the charge-limit flag, the environment, a test-data warning, and the SOAP call count.

An unknown or invalid identifier is a row with `found: false` and an `error`. It is not charged.

### Pricing

| Event | Price | When |
| --- | --- | --- |
| `company` | $0.003 | One delivered subject with `found: true` that was not skipped. |

No start fee and no separate charge per dataset row. VAT checks and nested local units are included in that price. Higher Apify plans pay less (down to $0.0024 per company). Set a maximum cost per run in Apify and the Actor stops before it with the rows saved so far. Platform usage is included in the price.

### Use cases

- **KYC and onboarding:** confirm a counterparty's name, NIP, REGON, KRS, legal form, seat and status from the official register.
- **CRM enrichment:** fill empty company fields from a list of NIPs.
- **Supplier lists:** check which identifiers still resolve, and which are closed or missing.
- **VAT status before payment:** `checkVatStatus` adds Czynny / Zwolniony / Niezarejestrowany. A VAT error does not drop the company row.
- **AI agents:** answer "who is this NIP?" through MCP.

### Privacy

REGON is a public official register. What third parties may receive is set by art. 44–45a of the Polish public statistics act. This Actor asks only for the company fields needed to identify a subject and its activity. It does not request phone, fax or email, including the company's own contacts. For a natural person registered in CEIDG it also does not request a separate first name, middle name or surname, and it does not request the phone or fax which the statistics office does not give to third parties from that register. The civil-partnership partners report is never called.

A sole trader's registered business name usually contains the owner's name. That name is the register entry, not a field this Actor builds from given names. Street, building and apartment for a sole trader are off unless `soleTraderFullAddress` is set. Minimisation beyond that, and the purpose of processing, are the user's responsibility.

### Source and terms

- Data: **Główny Urząd Statystyczny (Statistics Poland), REGON**, via BIR1.2 at `https://wyszukiwarkaregon.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc`. Each row carries `retrievedAt` and `sourceUrl`.
- VAT status, when requested: **Ministerstwo Finansów**, method WL2 at `https://wykazpodatnikowvat.mf.gov.pl/api2`. Status only. No accounts and no representatives.
- The test environment (`https://wyszukiwarkaregontest.stat.gov.pl`) serves anonymized data frozen around 8 November 2014. Rows from it have `environment: "test"`.
- GUS is not liable for results after this Actor has processed them. Check the register before you rely on a row.

### API key

You do not need a key. On Apify the Actor calls production BIR1.2 with its own user key, stored as a secret environment variable. If you have your own GUS key (GUS issues them free at `regon_bir@stat.gov.pl`), put it in `gusApiKey` and it is used instead. Keys are not written to the dataset, the key-value store, or the log.

When you run the source yourself without any key, set `useTestEnvironment` to use the public test key published in the GUS BIR1.2 technical instruction (section 2.1). Those rows have `environment: "test"` and come from the 2014 anonymized sample.

### FAQ

**Is there an API for Polish company data by NIP?** Yes. GUS publishes the REGON BIR1.2 service. This Actor turns a list of NIPs, REGONs and KRS numbers into one table.

**Can an AI agent look a company up?** Yes. Connect the Apify MCP server with this Actor as a tool.

**Do I need a key?** No. The Actor uses its own production key. You can pass your own in `gusApiKey`.

**Why was my row not charged?** `found` is false (invalid checksum, ambiguous identifier, or GUS returned no subject), or the row is a skipped sole trader, or that REGON was already saved in this run.

**Why is the street empty for a sole trader?** That is the default. Set `soleTraderFullAddress` if you need the street lines.

**What if the VAT service is down?** `vatStatus` is null, `vatError` says why, and the company row is still delivered.

**What if I hit my Apify cost limit?** The run stops before the limit, keeps the saved rows and ends SUCCEEDED.

### Integrations

Use the Apify API, scheduler, webhooks, Make, Zapier, n8n or a Google Sheets export as with any Actor. A scheduled run can re-check a supplier list; REGON numbers already in the run dataset are not charged again.

### Development

```bash
python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest
```

Tests run offline on recorded BIR1.2 responses. Personal tags in those fixtures are replaced with markers (`tests/test_privacy.py` checks that none of them reach the output, the log or SUMMARY). `scripts/gen_dataset_schema.py` writes the dataset schema. `scripts/run_test_env.py` performs one read-only run against the public GUS test environment.

For a local run with simulated prices set `ACTOR_TEST_PAY_PER_EVENT=true`, `APIFY_ACTOR_PRICING_INFO` from `examples/pricing_info.local.json` and `APIFY_CHARGED_ACTOR_EVENT_COUNTS='{"company":0}'`, delete `./storage`, then run `python3 -m src`.

### Disclaimer

Not affiliated with Główny Urząd Statystyczny or the Ministry of Finance. Data are fetched from those services and processed by this Actor.

### 🇵🇱 Po polsku

Aktor wyszukuje podmiot w rejestrze REGON (usługa BIR1.2 GUS) po NIP, REGON albo KRS i zwraca nazwę, identyfikatory, formę prawną, adres siedziby, PKD, daty i status. Opcjonalnie dopytuje status VAT metodą WL2 Ministerstwa Finansów (Czynny, Zwolniony albo Niezarejestrowany), bez rachunków bankowych i bez danych osób. Jednostki lokalne można dołączyć do rekordu firmy, bez dodatkowej opłaty, maksymalnie 50.

Klucz GUS nie jest potrzebny: na Apify aktor pyta produkcyjne BIR1.2 własnym kluczem. Własny klucz możesz podać w `gusApiKey`. Publiczne środowisko testowe GUS (dane zanonimizowane z 2014, `environment: "test"`) działa tylko przy uruchomieniu kodu bez klucza.

Dane osobowe: REGON jest jawny (art. 44–45a ustawy o statystyce publicznej). Aktor nie pobiera telefonu, faksu ani e-maila, także firmowego. Dla JDG nie pobiera imion i nazwiska jako osobnych pól ani telefonu i faksu, których osobom trzecim z CEIDG się nie udostępnia. Nie wywołuje raportu wspólników spółki cywilnej. Nazwa działalności gospodarczej często zawiera imię i nazwisko właściciela; to nazwa z rejestru. Ulica, numer budynku i lokalu JDG wracają tylko po ustawieniu `soleTraderFullAddress`. Cel przetwarzania należy do użytkownika.

Cena: $0.003 za podmiot z `found: true`, który nie został pominięty. Brak opłaty startowej i brak osobnej opłaty za wiersz datasetu. Wyższe plany Apify płacą mniej, do $0.0024 za firmę. Limit kosztu zatrzymuje run przed progiem i zostawia zapisane wiersze.

Źródło: Główny Urząd Statystyczny, REGON BIR1.2. GUS nie odpowiada za dane po przetworzeniu przez ten aktor. Aktor nie jest powiązany z GUS ani z Ministerstwem Finansów.

# Changelog

This Actor's version history is a separate document: https://apify.com/enterprising_hamster/polish-company-lookup-regon/changelog.md

# Actor input Schema

## `nips` (type: `array`):

Tax identifiers (NIP). Spaces, hyphens and a leading PL are ignored. Invalid checksums are returned as found=false and are not charged.

## `regons` (type: `array`):

9-digit subjects or 14-digit local units. Checksums are validated.

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

Court numbers. Shorter values are zero-padded to 10 digits. Looked up one at a time.

## `identifiers` (type: `array`):

Optional prefixes NIP:, REGON: and KRS:. Without a prefix, 9 or 14 digits are a REGON and 10 digits with a valid NIP checksum are a NIP. Anything else returns the error "ambiguous, use prefix".

## `gusApiKey` (type: `string`):

Optional. Your own production BIR1 user key from GUS. Leave empty: the Actor uses its own production key.

## `useTestEnvironment` (type: `boolean`):

When no production key is set, call the public GUS test service. Data is anonymized and frozen around 8 November 2014. Ignored when a key is set.

## `includeLocalUnits` (type: `boolean`):

Nest up to 50 local units (14-digit REGON) on each company. No extra charge. A 14-digit REGON in the input is its own row.

## `includeSoleTraders` (type: `boolean`):

When false, a sole trader (JDG) is returned with found=true and skipped=sole_trader and is not charged.

## `soleTraderFullAddress` (type: `boolean`):

Include street, building and apartment for a sole trader. Default is city, postal code, municipality, county and voivodeship only.

## `checkVatStatus` (type: `boolean`):

Ask the Ministry of Finance WL2 status method. Adds vatStatus, vatCheckedAt and vatRequestId. On failure the company is still returned with vatError. No bank accounts and no people.

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

Stop after this many charged companies. Empty means no cap. Not-found rows and skipped sole traders do not count.

## Actor input object example

```json
{
  "nips": [
    "7740001454",
    "6920000013",
    "5250007738",
    "5260250274"
  ],
  "regons": [
    "000331501"
  ],
  "krsNumbers": [],
  "identifiers": [],
  "useTestEnvironment": false,
  "includeLocalUnits": false,
  "includeSoleTraders": true,
  "soleTraderFullAddress": false,
  "checkVatStatus": false
}
```

# Actor output Schema

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

One item per subject: name, NIP, REGON, KRS, address, PKD, dates, optional VAT status.

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

Saved, found, not found, invalid, skipped sole traders, charge limit, environment and SOAP call count.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("enterprising_hamster/polish-company-lookup-regon").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("enterprising_hamster/polish-company-lookup-regon").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 '{}' |
apify call enterprising_hamster/polish-company-lookup-regon --silent --output-dataset

```

## MCP server setup

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

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/P8YBqbNVjwX0leKXE/builds/AEMWS4UulvF2UZSUU/openapi.json
