Polish Company Data & KYB: KRS/NIP/REGON + VAT & Bankruptcy
Pricing
from $5.00 / 1,000 company enricheds
Polish Company Data & KYB: KRS/NIP/REGON + VAT & Bankruptcy
Poland company data for KYB and KYC. Look up a firm by KRS, NIP or REGON: official KRS extract, Biała lista VAT white list status and IBAN check, PKD, capital, board, bankruptcy and liquidation.
Pricing
from $5.00 / 1,000 company enricheds
Rating
0.0
(0)
Developer
Yahya Nouali
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Polish Company Data & KYB
Look up a Polish company by KRS, NIP, or REGON and get a flat record for KYB, KYC, and lead generation: legal name, address, legal form, share capital, PKD codes, board and proxies, Biała lista VAT (VAT white list) status, bank-account checks, and a prominent bankruptcy / liquidation / restructuring flag.
The actor reads official, keyless registers:
- Krajowy Rejestr Sądowy open API (
api-krs.ms.gov.pl) — current extract, and the full extract when you ask for insolvency history - Ministry of Finance VAT white list (
wykazpodatnikowvat.mf.gov.pl, legacy hostwl-api.mf.gov.pluntil 1 December 2026)
An optional GUS REGON (BIR1) lookup runs only when you pass your own user key. That is how sole traders (JDG), who are not in KRS, can still be resolved when the white list is not enough.
Invalid identifiers and unknown companies are returned as rows and are not charged.
Why this is useful
- Onboard a Polish counterparty and see, in one row, whether the register shows bankruptcy, liquidation, or restructuring.
- Check that an invoice account is on the VAT white list before a payment. Polish tax rules (Tax Ordinance art. 117ba) attach consequences to paying more than 15,000 PLN to an account that is not on the list. Keep the
vatRequestIdfrom the Ministry; this actor is not the official certificate. - Enrich a lead list with legal name, address, PKD, and capital.
- Monitor a portfolio. The first run stores a baseline and is not charged. Later runs return only real changes in status, address, name, board, PKD, VAT status, or insolvency entries.
Input
| Field | Default | Meaning |
|---|---|---|
companies | — | Objects { id, type?, checkIbans? } or plain strings. type is auto, nip, regon, or krs. |
identifierList | — | Extra ids separated by newlines, commas, or spaces. |
includeBoard | true | Management body, supervisory board, and proxies. The public KRS API masks personal names (for example D**** B****), so full names are not provided. PESEL is never output. |
includeInsolvencyHistory | false | Also fetch OdpisPelny (ended proceedings). Extra charge in enrich mode when the extract is retrieved. |
mode | enrich | monitor stores snapshots in a named key-value store and emits changes only. |
monitorStoreName | polish-company-monitor | Reuse this name so the next run sees the baseline. |
regonApiKey | empty secret | Your GUS BIR1 key. Never written to the dataset. |
maxCompanies | 300 | The run fails instead of truncating. Maximum 3000. |
Detection:
- 9 digits, or 14 digits: REGON, checksum required. A 14-digit value that is a 9-digit REGON plus
00000(how KRS stores it) is accepted as that REGON-9. - 10 digits with a valid NIP checksum: NIP, unless
typeiskrs. - 10 digits that fail the NIP checksum and start with
0: KRS. A KRS number is 10 digits with leading zeros. - 10 digits with no leading zero that fail the NIP checksum: invalid, unless
typeiskrs. These are not looked up, so they are not returned asnot_found. - 1–8 digit numbers: KRS, zero-padded to 10.
- Prefixes
NIP,REGON, andKRSare accepted.
{"companies": [{ "id": "7740001454", "checkIbans": ["PL61109010140000071219812874"] },{ "id": "KRS 28860" },{ "id": "610188201", "type": "regon" }],"includeBoard": true,"includeInsolvencyHistory": false,"mode": "enrich"}
7740001454 is the public NIP of ORLEN S.A., a useful connectivity check. It is not an endorsement.
Output
One JSON object per company, flat enough for CSV. Nested lists are JSON strings (insolvencyEntriesJson).
Important fields:
found,error,errorMessage—invalid_identifier,not_found,vat_quota_exceeded,source_unavailableinsolvencyFlag—trueorfalsewhen a KRS extract was read,nullwhen insolvency was not checked (for example a sole trader found only on the white list)insolvencyStatus—none,bankruptcy,liquidation,restructuring,multiple,unknownvatStatus—active,exempt,not_registered,removed,unknown,unavailablestatus—active,in_bankruptcy,in_liquidation,in_restructuring,suspended,struck_off,unknownname,legalForm,nip,regon,regon14,krs- address parts,
shareCapitalAmount,pkdMainCode,pkdCodes boardMembers,supervisoryBoard,proxiesasName (role)joined with;. The public KRS API returns personal names already masked, for exampleD**** B****. Full names are not provided, and this actor does not try to recover them.vatAccountNumbers,ibanChecksasnrb:assigned,not_assigned,local_match,local_miss,invalid, orunavailablesources,sourceKrsUrl,sourceVatUrl,vatRequestIdchargedEvents,partial,warnings
local_match / local_miss means the official account-check quota was spent and the actor compared the number with the account list already returned by search. That is not the Ministry's TAK/NIE answer, and it can miss a virtual account. unavailable means there was nothing to compare.
Illustrative enrich row. Board names from the public KRS API look like D**** B****; the other fields show the shape, not a live extract:
{"found": true,"insolvencyFlag": false,"insolvencyStatus": "none","vatStatus": "active","status": "active","name": "ORLEN SPÓŁKA AKCYJNA","legalForm": "SPÓŁKA AKCYJNA","nip": "7740001454","regon": "610188201","krs": "0000028860","address": "CHEMIKÓW 7, 09-411 PŁOCK, POLSKA","shareCapitalAmount": 1451177561.25,"shareCapitalCurrency": "PLN","pkdMainCode": "19.20.Z","pkdMainDescription": "WYTWARZANIE I PRZETWARZANIE PRODUKTÓW RAFINACJI ROPY NAFTOWEJ","boardMembers": "D**** B**** (PREZES ZARZĄDU)","vatStatusRaw": "Czynny","vatAccountCount": 236,"ibanChecks": "61109010140000071219812874:assigned","sources": "krs; vat_whitelist","chargedEvents": "company-enriched","mode": "enrich"}
Monitor mode writes a short baseline on the first run (changeType: baseline, chargedEvents empty). Later runs omit companies that did not change. A change row has changeType: changed, changedFields, previousJson, and currentJson.
Pricing
Pay per event. Figures are the Store prices to configure; see PUBLISHING.md.
| Event | Price | When |
|---|---|---|
company-enriched | $0.005 | Enrich mode, and a registry record was found. Primary event. |
insolvency-history | $0.002 | Enrich mode, and the full KRS extract was retrieved. |
change-detected | $0.015 | Monitor mode, and a watched field changed. |
Not found, invalid, the monitor baseline, and unchanged monitor checks are free. Disable the synthetic per-dataset-item charge so those free rows stay free.
How to run
Node.js 20 or newer.
npm installnpm testnpm run buildmkdir -p storage/key_value_stores/defaultcp examples/input.json storage/key_value_stores/default/INPUT.jsonnpm start
Results land in storage/datasets/default. Outside Apify, billingNote is not_billed_outside_apify and nothing is billed.
Live check against the public registers (uses one VAT search and one KRS read):
$npm run smoke
Push to Apify from this directory, or from the tarball produced by npm run package:
npm run packagetar -xzf polish-company-kyb-actor.tar.gznpm installapify push
The image is apify/actor-node:20. No Apify username is baked into the project. In the Store publication form set categories to Lead generation (LEAD_GENERATION) and Business (BUSINESS). The actor manifest schema has no categories field, so they are recorded in PUBLISHING.md instead of .actor/actor.json.
Use cases
- KYB / KYC onboarding of a Polish company before a contract or a payment.
- Accounts-payable white-list checks for a batch of supplier NIPs and IBANs.
- Lead enrichment: PKD, capital, address, and the masked names of people who represent the company.
- Portfolio monitoring for new insolvency entries, address changes, or a VAT status flip.
- Gap-fill for a sole trader when you already hold a GUS REGON key.
Integrations: Make, Zapier, n8n
You can call this Actor from no-code tools through Apify's official integrations. Use its Actor ID SXToneTLvcjlKKMPk, and connect each tool with OAuth or your Apify API token. Never put the token in the Actor input.
- Make: in the Apify app, add Run an Actor and set Run synchronously to Yes. Then add Get Dataset Items with the run's default dataset ID, and map the rows to Google Sheets, a CRM or Slack. For long runs, use the Watch Actor Runs trigger instead.
- Zapier: the Apify app has the Run Actor action. A synchronous run has a 30-second hard timeout, so for larger lists start the run and use the Finished Actor Run trigger with Fetch Dataset Items.
- n8n: install the official node
@apify/n8n-nodes-apify. It is a verified community node on n8n Cloud; on self-hosted n8n, add it under Settings > Community Nodes. Use Run an Actor and Get Dataset, or the Apify trigger for finished runs.
Example input:
{"mode": "enrich", "companies": [{"id": "7740001454"}], "includeBoard": true}
Scheduled monitor to Slack or Sheets
- Save a monitor input as an Actor task and keep the same store name on every run:
{"mode": "monitor","companies": [{"id": "7740001454"}],"monitorStoreName": "polish-company-monitor"}
- In Apify Console > Schedules, run the task on a cron such as
0 7 * * 1(every Monday at 07:00), with your timezone selected. - On the task's Integrations tab, add Slack or an HTTP webhook on Run succeeded. You can also use Make Watch Actor Runs, Zapier Finished Actor Run or the n8n Apify trigger.
- Fetch the dataset items and keep only the change rows:
changeTypeis"changed". The first run only stores the baseline and is free.
HTTP API
This call runs the Actor and returns the dataset rows in one request. Synchronous runs time out after 300 seconds, so use /runs for big lists.
curl -X POST "https://api.apify.com/v2/acts/SXToneTLvcjlKKMPk/run-sync-get-dataset-items" \-H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"mode": "enrich", "companies": [{"id": "7740001454"}], "includeBoard": true}'
FAQ
Where does the data come from?
KRS Open API, Ministry of Justice, no key: GET /api/krs/OdpisAktualny/{krs} and OdpisPelny/{krs} with rejestr=P (entrepreneurs) or S (associations, foundations, and the other entities in that register) and format=json. The API does not search by NIP, REGON, or name. This actor learns the KRS number from the VAT white list or, if you supply a key, from BIR1.
VAT white list, Ministry of Finance / KAS, no key. Since 15 October 2026 the production host is https://wykazpodatnikowvat.mf.gov.pl/api. https://wl-api.mf.gov.pl keeps working until 1 December 2026; this actor tries the new host first and falls back to the legacy host. Search accepts up to 30 NIPs or REGONs per call. The check method answers TAK or NIE for one NIP plus account. WL2 (/api2/status/nip/{nip}) returns only the VAT status and is used when the search quota is spent.
REGON, GUS BIR1 SOAP, only with your key, and only when KRS did not already provide the name, REGON, or PKD.
What are the reuse terms?
Checked against the publishers' notices as of 24 October 2026. This actor does not grant a licence of its own. You get what the publisher gives, and you have to attribute them.
KRS. The open API was announced by the Ministry of Justice on 8 March 2022 under the Act of 11 August 2021 on open data and reuse of public sector information. Article 4b of the KRS Act says registry data are made available for reuse under that act, including via API. The Ministry has not published a separate Creative Commons deed for the API. Reuse is statutory and free of charge for the keyless Open API. Attribute Ministerstwo Sprawiedliwości — Krajowy Rejestr Sądowy. The published scope is the current and full extract issued by Centralna Informacja KRS, with the Ministry's own GDPR limits already applied. A wider "Full API" that needs a ministerial decision is a different service; this actor does not call it.
VAT white list. The list is kept under article 96b of the VAT Act. The Ministry's API notice (gov.pl, Krajowa Administracja Skarbowa) sets operational limits and does not attach a Creative Commons licence. The Ministry's general reuse page says public-sector information is provided for reuse free of charge, that the Ministry is not liable for what a reuser does with it, and that the Ministry may set objective, proportionate, non-discriminatory conditions. Attribute Ministerstwo Finansów — Wykaz podatników VAT. vatRequestId is the Ministry's confirmation of that query.
REGON / BIR1. The register is public under articles 42–45a of the Act of 29 June 1995 on public statistics. Article 45 lists what third parties may receive (name, address, NIP, legal form, activity including the main PKD, dates, the registry identifier, local units). Phone, fax, email, and website of a natural person in CEIDG are not disclosed to third parties. BIR1 is free but requires a user key and acceptance of the GUS regulamin for commercial users: no flooding, no extra accounts to dodge limits, no scanning of sequential identifiers. Published guidance is about 3 requests per second and 120–150 per minute. You remain the BIR1 customer. Attribute Główny Urząd Statystyczny — rejestr REGON.
What about GDPR and board members?
The public KRS Open API masks board, supervisory-board, and proxy names. A given name and surname come back like D**** B****, not as a full name, and this actor returns that masked string as published. It does not reconstruct a name. PESEL, when a source field is present, is also masked by the Ministry (values such as 5**********); this actor drops PESEL anyway, including PESEL on the VAT white list. These fields are public registry data with the Ministry's own limits already applied.
You are an independent controller for your own purpose (KYB, lead generation, monitoring). The lawful basis is yours to decide. Do not use this actor to download the whole register: it only accepts identifiers you already have. Sole traders are natural persons; treat them with extra care. This output is not legal advice.
What happens when the VAT quota runs out?
The Ministry allows 100 search requests per day from an IP address, each for up to 30 entities, 5,000 account checks per day, and 50,000 WL2 status calls per day. The counter resets at midnight Europe/Warsaw. This actor batches searches, caches repeats inside the run, and stores the day's usage in the key-value store polish-company-vat-quota so later runs on the same Apify account back off. When the quota is hit, VAT fields become unavailable (or WL2 fills vatStatus only). The company row still succeeds if KRS or REGON identified it. The run does not fail.
On the Apify platform the egress IP can be shared. Another tenant can burn the Ministry's IP quota. The actor then degrades the same way.
Which insolvency entries count?
insolvencyFlag is true only for a current bankruptcy, liquidation, or restructuring entry (or a company name ending in w upadłości, w likwidacji, or w restrukturyzacji). Ended proceedings stay in the history list with active: false and do not keep the flag on. Mergers and demergers are ignored. Suspension and striking off change status but are not insolvency. The combined KRS section that mixes restructuring and orderly liquidation is split on the wording: text containing likwidac is liquidation; other wording in that section is restructuring.
Is a sole trader in KRS?
No. A JDG lives in CEIDG and REGON. The white list often has the name, address, REGON, and VAT status. PKD and the activity dates then need your BIR1 key. insolvencyFlag stays null because KRS was not consulted. There is no CEIDG call in this actor.
Development
npm testnpm run buildnpm run smoke
Vitest covers checksums, KRS current and full extracts, insolvency classification, the VAT batcher and quota breaker, monitor diffs, and the charging rules. HTTP is mocked. npm run smoke is the live test and is intentionally not part of CI.
Po polsku
To narzędzie do wzbogacania danych polskich firm pod KYB, KYC i lead generation. Na wejściu podajesz NIP, REGON albo numer KRS. Na wyjściu dostajesz płaski rekord: nazwę, adres, formę prawną, kapitał zakładowy, kody PKD, zarząd i prokurentów, status na białej liście VAT, wynik sprawdzenia rachunku oraz wyraźną flagę upadłości, likwidacji albo restrukturyzacji.
Źródła są urzędowe i bezpłatne:
- Otwarte API KRS Ministerstwa Sprawiedliwości (
OdpisAktualnyi, na życzenie,OdpisPelny). API nie szuka po NIP ani REGON — numer KRS bierzemy z białej listy albo z BIR1, jeśli podasz własny klucz GUS. - Wykaz podatników VAT Ministerstwa Finansów. Od 15 października 2026 r. adres produkcyjny to
wykazpodatnikowvat.mf.gov.pl. Starywl-api.mf.gov.pldziała do 1 grudnia 2026 r. - Opcjonalnie REGON (BIR1), wyłącznie Twoim kluczem użytkownika, i tylko gdy KRS nie oddał nazwy, numeru REGON albo PKD. Jednoosobowa działalność nie jest w KRS.
Suma kontrolna NIP i REGON jest sprawdzana przed zapytaniem. Błędny identyfikator i brak podmiotu w rejestrze nie są płatne.
Cennik za zdarzenie: firma znaleziona 0,005 USD, historia postępowań z odpisu pełnego 0,002 USD, wykryta zmiana w trybie monitorowania 0,015 USD. Pierwsze uruchomienie monitora zapisuje punkt odniesienia i nic nie kosztuje. Limit białej listy to 100 zapytań search dziennie po maksymalnie 30 podmiotów. Po wyczerpaniu limitu pola VAT dostają wartość unavailable, a bieg aktora się nie przerywa.
Publiczne API KRS zwraca imiona i nazwiska członków zarządu, rady nadzorczej i prokurentów w formie zamaskowanej, na przykład D**** B****. Pełnych nazwisk nie ma i aktor ich nie odtwarza. PESEL, jeśli w ogóle występuje, jest zamaskowany i aktor i tak go usuwa. Dziesięciocyfrowy numer bez zera na początku, który nie przechodzi sumy kontrolnej NIP, jest odrzucany jako błędny identyfikator, chyba że jawnie ustawisz typ krs. Numer KRS ma 10 cyfr i zera wiodące. To nie jest porada prawna ani urzędowe zaświadczenie — identyfikator zapytania vatRequestId wydaje Ministerstwo Finansów.
Limitations
See PUBLISHING.md for the charge sheet. Operational limits are also collected in the FAQ above: no KRS search by NIP, shared VAT IP quota, no CEIDG, no Full KRS API, and no claim that a local_match IBAN check is the Ministry's TAK/NIE answer. The public KRS API masks board members' names (for example D**** B****), so full names are not provided.