Poland KRS Scraper & Bulk Company Lookup - Court Register avatar

Poland KRS Scraper & Bulk Company Lookup - Court Register

Pricing

from $4.38 / 1,000 entity returneds

Go to Apify Store
Poland KRS Scraper & Bulk Company Lookup - Court Register

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

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

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.yyyy and are returned as ISO yyyy-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 as D) 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, krs and regon instead of nameMasked; and the register sometimes lists a seat with no published data at all, which is kept as an all-null entry so that officerCount matches 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 carries nipStatus: "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 as null.
  • Suspension of activity is a list of suspension/resumption pairs; activitySuspended is 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, arrearsTotal and arrearsCurrency, and the raw section keys are listed in section4Keys so nothing is hidden: 3 of 93 have section 4 entries. Section 6 (liquidation, dissolution, mergers, restructuring, suspension) is summarised the same way in section6Keys; 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 giveWhat you getCharged
ORLEN or 7740001454X (not digits)bad-input, not sent to the registerNo
61018820100000 (a REGON, 14 digits)bad-input, explaining that only the KRS number can be looked upNo
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 entityNo
28860Padded to 0000028860 and looked upYes, if found
0000000001 (never assigned)not-found, after both registers answered 404No
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 todayNo
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 seenNo
The same number twice, formatted differentlyLooked up once, charged once; the second gets duplicate-inputNo
A 200 answer whose numerKRS differs from the number askedfailed - a different entity is never delivered under your numberNo

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

FieldWhat it does
krsNumbersKRS 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.
registryP (entrepreneurs, default) or S (associations and foundations). If the number is not in the chosen register the other one is tried.
fullExtractAlso read the full extract and add the entry history and previous names to each row (two requests per number). Default off.
maxResultsStop 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.
  • positionStateCode is the register's stanPozycji returned 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.