Poland KRS Scraper & Bulk Company Lookup - Court Register
Pricing
from $4.38 / 1,000 entity returneds
Poland KRS Scraper & Bulk Company Lookup - Court Register
Bulk lookup of Polish companies, foundations and associations by KRS number from the Ministry of Justice open API: name, legal form, NIP, REGON, address, share capital, PKD, board and shareholders, liquidation, suspension and arrears flags, and struck-off entities with their deletion date.
Pricing
from $4.38 / 1,000 entity returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Poland KRS Scraper & Bulk Company Lookup
Look up Polish companies, foundations and associations by KRS number in bulk and get one row per entity from the National Court Register (Krajowy Rejestr Sądowy): registered name, legal form, NIP, REGON, registered address, e-mail and website where filed, share capital, PKD activities, the management board and supervisory board (with the register's own masking of personal names), proxies (prokurenci), shareholders and partners, liquidation, dissolution, suspension and tax-arrears flags, filing history of financial statements, and for entities that have been struck off, the last recorded values and the deletion date. The data comes from the Ministry of Justice open API (api-krs.ms.gov.pl). No API key, no proxy, no scraping of the court portal.
{"krsNumbers": ["0000028860", "0000026438", "0000006865"],"registry": "P"}
Paste KRS numbers one per line or separated by commas; 28860, KRS 28860, 0000-028-860 and 0000028860 are the
same entity. A number with a decimal point (28860.0, which is what a spreadsheet or pandas writes when the column is
numeric) is refused with a reason instead of being guessed - see the table in 5 below.
Only the KRS number can be looked up. The register's API has no search by name, NIP or REGON, and neither has this Actor. If you only have a company name, find its KRS number first (for example on the court register portal), then paste the numbers here.
What this does that a plain API call does not
Everything below was measured against the live register on 2026-09-12, not read from documentation. Every count below is out of the same 93 entities: the 93 current extracts the register returned that day (well-known companies, random numbers from eight ranges of the register, and three entities from the S register), counted once per KRS number. Two further entities are covered only by a full extract, because they have been struck off and their current extract is empty (see 1 below); they are not part of the 93. All of them are kept in this Actor's test fixtures and recounted by its tests, so every number here can be checked against the data it was measured from.
1. Struck-off entities are not reported as "not found"
For an entity that has been struck off the register, the current extract endpoint answers HTTP 204 with an empty
body - a status the official documentation does not list. Many tools turn that into "no such company". Here a 204
triggers a read of the full extract (odpis pełny), which the register still serves for deleted entities, and the
row comes back with deleted: true, deletedOn (the date of the entry "WYKREŚLENIE Z KRAJOWEGO REJESTRU SĄDOWEGO"),
the last recorded name, legal form, NIP, REGON, address and share capital, the previous names, and the full list of
register entries. Grupa Lotos (0000106150, merged into Orlen in 2022) and PGNiG (0000059492) are examples. These rows
are charged like any other, because they answer the question you asked; the officers and shareholders are left
empty because that board no longer exists.
2. A number in the other register is found anyway
Every KRS number is in exactly one of two registers: P (entrepreneurs: companies, cooperatives, foreign branches)
or S (associations, foundations, other non-profit organisations, public healthcare institutions). Asking the API
for a foundation in the P register returns 404. Here, when the chosen register answers 404, the other register is
tried once; if the entity is there, the row is delivered with registry set to where it was found and a note saying
so. Only when both answer 404 is the row not-found.
3. Personal data: what the register masks stays masked, and nothing more is added
The open API of the Ministry of Justice anonymises natural persons: board members, supervisory board members,
proxies, liquidators and individual shareholders come back as I******* F*****, and PESEL numbers as 5**********
(the API with full names is available only to bodies designated by a decision of the Minister). This Actor returns
exactly those masked names together with the role, and never returns a PESEL, masked or not. Free-text fields
that in the sample contained unmasked personal names - the description of a liquidation (which named a foundation's
founder) and the description of a proxy's powers (which named a branch proxy) - are not returned as text; only the
liquidation date, the dissolution circumstance and the type of proxy (the part before the first comma, for example
PROKURA SAMOISTNA) are.
4. Values the raw data gets awkward
- Amounts arrive as strings with a decimal comma (
1451177561,25). They are returned as numbers (shareCapital: 1451177561.25) with the currency and the raw string. - Dates arrive as
dd.mm.yyyyand are returned as ISOyyyy-mm-dd. - PKD codes arrive as three parts (dział, klasa, podklasa) and are joined as
19.20.Z. When the register holds a group-level entry (klasa with one digit) the code is returned as the group,20.1, not padded into a class that was never registered; old section-level entries from PKD 2004 (a single letter such asD) are returned as that letter. - A board seat is not always a person. In partnerships the general partner is a company (Lidl sp. z o.o.
represents Lidl sp. z o.o. sp.k.), so an officer can carry
name,krsandregoninstead ofnameMasked; and the register sometimes lists a seat with no published data at all, which is kept as an all-null entry so thatofficerCountmatches the register. - REGON is stored as 14 digits ending in
00000; both the 14-digit form (regon) and the 9-digit form (regon9) are returned. A revoked NIP carriesnipStatus: "UCHYLONY"with the decision date: 4 of 93 had a revoked NIP. - Foreign parent shareholders are stored with the placeholder KRS
0000000000; it is returned asnull. - Suspension of activity is a list of suspension/resumption pairs;
activitySuspendedis true only when the latest suspension has no resumption date. 11 of 93 carry a suspension entry, most of them resumed. - Section 4 (arrears and enforcement) is summarised as
arrearsCount,arrearsTotalandarrearsCurrency, and the raw section keys are listed insection4Keysso nothing is hidden: 3 of 93 have section 4 entries. Section 6 (liquidation, dissolution, mergers, restructuring, suspension) is summarised the same way insection6Keys; 3 of 93 are in liquidation. - E-mail and website are returned only when the entity filed them: 23 of 93 have an email, 39 a website.
5. Typos and repeats are never reported as missing companies
| What you give | What you get | Charged |
|---|---|---|
ORLEN or 7740001454X (not digits) | bad-input, not sent to the register | No |
61018820100000 (a REGON, 14 digits) | bad-input, explaining that only the KRS number can be looked up | No |
28860.0 (a spreadsheet or pandas wrote a numeric column) | bad-input, saying a KRS number is a whole number. The point is not removed and the number is not guessed to be 28860: 0000288600 is a different company that really exists, so a silent "fix" would sell you the wrong entity | No |
28860 | Padded to 0000028860 and looked up | Yes, if found |
0000000001 (never assigned) | not-found, after both registers answered 404 | No |
| A number the register refuses (HTTP 400) | rejected-by-source, with the register's own words. This does not happen in practice: every input the register would refuse is stopped here as bad-input before anything is sent, so the row exists only in case the register starts refusing something it accepts today | No |
| The register does not answer (no response, 429, 5xx) | Retried after 2, 5, 10 and 20 seconds; if it still fails, failed with every status seen | No |
| The same number twice, formatted differently | Looked up once, charged once; the second gets duplicate-input | No |
A 200 answer whose numerKRS differs from the number asked | failed - a different entity is never delivered under your number | No |
6. The register is used gently
Lookups are made one at a time, never in parallel, with a 0.25-second pause between them. Measured in production on
2026-09-12, 38 numbers took 22.6 seconds end to end over 44 requests (a number that is not in the register you chose
is looked up in the other one as well) - 0.59 seconds per lookup including the pause - so the cap of
2,000 numbers takes about 20 minutes, and 1,000 with fullExtract (two requests per number, about 1.1 seconds
each) about 18 minutes, both well inside Apify's default one-hour run limit. Anything beyond the cap is not looked up
and is listed in an uncharged row saying how many. In a test of 30 back-to-back requests from a home connection on the
same day, all 30 answered HTTP 200 with no rate limiting and no Retry-After, taking 1.35-2.53 seconds each (average
1.78); the register is slower to reach from outside a data centre than from Apify.
What you get
Identity: krs, registry (P or S), registryName, extract (current or full), deleted, deletedOn, name,
legalForm, isForeignBranch, foreignParentName, foreignRegister, regon, regon9, nip, nipStatus,
nipStatusOn, previousRegister, previousRegisterNumber, publicBenefitStatus (OPP), duration.
Register header: registeredInKrsOn, lastEntryNumber, lastEntryOn, dataAsOf, positionStateCode (the
register's own stanPozycji, returned as is), registryCourt.
Address: country, voivodeship, county, municipality, city, street, buildingNumber, unitNumber,
postalCode, postOffice, addressLine, email, website, eDeliveryAddress.
Capital: shareCapital, shareCapitalCurrency, shareCapitalRaw, paidCapital, totalShares, shareNominalValue.
People and owners: representationBody, representationRule, officerCount, officers (masked name, role,
suspended), supervisoryBody, supervisorCount, supervisors, proxyCount, proxies (masked name, type),
shareholderCount, shareholderCompanies, shareholderPersons, shareholders (type, name or masked name, KRS,
REGON, shares held, whether they hold all shares, limited-partner flag and sums for partnerships).
Activity: mainActivityPkd, mainActivity, otherActivityCount, otherActivities, purpose (statutory purpose of
an organisation in the S register), firstFinancialYearEnd, financialStatementCount,
latestFinancialStatementFiledOn, latestFinancialStatementPeriod.
Status flags: inLiquidation, liquidationOpenedOn, liquidatorCount, dissolutionCircumstance, dissolutionDate,
activitySuspended, activitySuspendedOn, activityResumedOn, mergerDivisionTransformationCount, arrearsCount,
arrearsTotal, arrearsCurrency, section4Keys, section5Keys, section6Keys, branchCount, branches.
History (with fullExtract, and always for struck-off entities): entryCount, entries (number, description,
date, court, case number, date it became final), previousNames.
Every row also has status, note, input (what you typed), source, sourceUrl and checkedAt.
Only rows with status = ok are charged. Rows that explain an invalid number, a number in neither register, a
refusal, a failed lookup, a repeated input or an input that was not looked up are free.
Input
| Field | What it does |
|---|---|
krsNumbers | KRS numbers, one per line or separated by commas or semicolons, with or without leading zeros or a KRS prefix. Up to 2,000 per run (1,000 with fullExtract). If left empty, ORLEN S.A. (0000028860) is looked up as an example, and the log says so. |
registry | P (entrepreneurs, default) or S (associations and foundations). If the number is not in the chosen register the other one is tried. |
fullExtract | Also read the full extract and add the entry history and previous names to each row (two requests per number). Default off. |
maxResults | Stop after this many lookups; the rest are listed in an uncharged row. Default and maximum 2,000; a value below 1 is treated as 1. |
krsNumbers carries no default value, so nothing is ever added to your list that you did not type.
Limits worth knowing
- The register's API is a lookup by number only. There is no search by name, NIP, REGON, city or PKD.
dataAsOf(stanZDnia) is the register's own "state as of" date for the extract; the data is as current as the court's last entry.positionStateCodeis the register'sstanPozycjireturned without interpretation: 1 was observed on every active entity in the P register, 3 on entities in the S register, 4 on foundations registered in the P register and 2 on struck-off entities in the full extract. Its official meaning is not published with the API.- Personal names are masked by the source (see 3 above). If you need the full names of board members, this Actor cannot provide them.
Source and licence
The data is served by the open API of the National Court Register run by the Polish Ministry of Justice
(api-krs.ms.gov.pl, documented at prs.ms.gov.pl/krs/openApi), launched under the Act of 11 August 2021 on open
data and the re-use of public sector information. The dataset entry on the national open-data portal
(dane.gov.pl, dataset 27606) states the licence as CC0 1.0 and that the API "does not require a token and has no
download limits; the data is made available in the public domain" ("API nie wymaga tokenu i nie posiada limitów
pobrań. Dane udostępniane są w domenie publicznej."). api-krs.ms.gov.pl publishes no robots.txt. This Actor makes
plain HTTPS requests to that API, one at a time, and does not use the court portal's web pages.
Support
Found a KRS number that comes back wrong? Open an issue in the Issues tab with the number and what you expected.