Poland Company Registry — KRS/REGON Official API
Pricing
from $2.72 / 1,000 poland company registry — krs/regon official apis
Poland Company Registry — KRS/REGON Official API
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.
Pricing
from $2.72 / 1,000 poland company registry — krs/regon official apis
Rating
0.0
(0)
Developer
Vitalii Bondarev
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
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:
- Email
regon_bir@stat.gov.plwith: 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). - GUS says turnaround is "coordinated individually" — there's no published SLA. Budget a few business days.
- 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, whenDataZakonczeniaDzialalnosci(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_confidenceis 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.pyare 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 tonull+ a warning, never a crash. Runscripts/probe.pywith a real production key to validate against live data before a large run. - Live validation: run
python3 scripts/probe.py(KRS, no key needed) orpython3 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:
{"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):
{"krsNumbers": ["0000023302"]}
With REGON enrichment (requires your own GUS key):
{"nipNumbers": ["7342867148"],"regonApiKey": "<YOUR_REGON_API_KEY>"}
Example output row an agent can reason over directly:
{"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, Make, Zapier.
- Webhooks — fire your own endpoint the moment a run finishes, to push results straight into your pipeline (docs).
- MCP server — expose this actor as a tool to Claude, Cursor, or any MCP client so an AI agent can pull this data mid-conversation (guide).
- API & SDKs — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.
See all Apify 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:
Usage statistics
This Actor creates a small, content-free summary at the end of each run. It is used only to monitor reliability and improve this Actor. A copy is saved as USAGE_STATS in your own Apify key-value store, so you can see the exact record created for your run.
Set disableUsageStats to true in the input to opt out. Nothing is sent then; your USAGE_STATS record only says that statistics were disabled.
Only these fields are recorded:
- schema version, Actor name and build number;
- UTC start and finish hour (not a precise timestamp);
- run duration, number of results and time to the first result, each as a coarse range;
- whether the result was empty, the end status, and an error type from a fixed list;
- memory setting and counts of charged events;
- names of the input fields you set, never their values;
- the selected option for input fields that offer a fixed list of choices (for example a sort order).
We do not collect input text, search terms, URLs, domains, usernames, email addresses, names, proxy credentials, tokens, scraped records, output items, raw error messages, stack traces, or hashes of any of those values. Records are kept for no longer than 13 months, used only as aggregated operational statistics, and never sold or shared.
Additional fields (Phase 2)
This Actor also records your Apify user ID, whether Apify marks the account as paying, the size range of list inputs, the selected country when the input offers a fixed list of countries, and one category from a fixed Actor taxonomy. We use these fields only for aggregate reliability, repeat-use and cross-Actor analysis; reports suppress any cell with fewer than five distinct users.
The same disableUsageStats: true input flag turns these fields off too. The user ID is removed after 13 months; we do not export, sell, share, or attempt to re-identify this data.
Run-outcome signals (v2)
To learn whether a run did what it was asked to do, the record also holds a few more coarse ranges and yes/no flags. None of them contains content:
- the result limit you asked for (a range, when the input has one) and what share of it was delivered;
- results delivered per input item you listed (a range);
- output quality as ranges: how fully the result fields were filled, the share of rows that look like errors, the share of duplicate rows, and how many different fields appeared. These are counted in memory while results are saved; no result content is kept;
- how the run was started (console, API, schedule, webhook, another Actor);
- how it ended: stopped by you, timed out, reached the requested limit, stopped by the charge limit, and how many times the platform moved the run;
- if this Actor reports it: how many items to process worked or failed (ranges) and one failure reason from a fixed list;
- a short code made from the names of the input fields you set, never their values.
Repeat-run fingerprint (v2)
When your Apify user ID is recorded (see above), the record also holds an 8-character one-way code made from your input (proxy settings left out) and this Actor's name. It only lets us see that the same account ran the same input again soon after an unsatisfying run; we never see the input itself. It is stored only in the database, never published, and reports use it in aggregate with the same five-user minimum. It is the one exception to the statement above that no hashes are collected, and disableUsageStats: true turns it off.