KRS Validation in Node.js
The Polish National Court Register number — a 10-digit identifier for companies, associations, and foundations. Here's how to validate it and look up entity data.
In this guide
1. What is a KRS number?
KRS (Krajowy Rejestr Sadowy — National Court Register) is a centralised public registry maintained by the Ministry of Justice of Poland. Every company, association, foundation, and certain other legal entities registered in Poland receives a unique KRS number. It serves as the primary identifier in:
- B2B contracts and invoicing between Polish companies
- Public procurement and tender processes
- Due diligence and KYC/AML checks
- Cross-referencing with NIP (tax) and REGON (statistical) registries
- Court filings and legal proceedings
The KRS database is split into two main registries:
| Registry | Code | Contains |
|---|---|---|
| Register of Entrepreneurs | P | Sp. z o.o., S.A., partnerships, cooperatives, state enterprises |
| Register of Associations | S | Associations, foundations, public benefit organisations (OPP) |
2. KRS structure
A KRS number is a simple 10-digit zero-padded sequential number. Unlike NIP or REGON, KRS does not contain a check digit — there is no built-in checksum algorithm to verify structural correctness.
| Property | Value |
|---|---|
| Length | 1 to 10 digits (zero-padded to 10 in the official registry) |
| Character set | Digits only (0–9) |
| Assignment | Sequential — numbers are assigned in order of registration |
| Check digit | None — no built-in checksum |
| Entity | KRS | Registry |
|---|---|---|
| CREACT.DEV SP. Z O.O. | 0000896246 | P (Entrepreneurs) |
| PKN ORLEN S.A. | 0000028860 | P (Entrepreneurs) |
3. Why KRS validation matters
Company verification in B2B transactions
Polish law requires KRS numbers on invoices and contracts for registered entities. Validating the KRS before signing a contract confirms the counterparty actually exists and is registered with the court.
NIP and REGON cross-referencing
Every KRS entry contains the entity's NIP (tax number) and REGON (statistical number). By looking up a KRS number, you can verify all three identifiers match, catching inconsistencies that might indicate fraud or data entry errors.
Due diligence and compliance
KYC/AML processes for Polish entities require checking the KRS registry. The lookup reveals the legal form, registered address, and whether the entity holds OPP (public benefit organisation) status.
Public procurement
Tenders in Poland require bidders to provide a valid KRS number. Automated validation ensures that only properly registered entities can participate, reducing manual verification workload.
4. The right solution: one API call
The IsValid KRS API handles format validation and government registry lookup in a single GET request:
Format validation
1-10 digits, all numeric, zero-padded
Government registry lookup (optional)
Entity name, legal form, NIP, REGON, and full address from the official KRS database
NIP / REGON extraction
Cross-reference tax and statistical identifiers from a single KRS query
Address data
Full registered address including city, voivodeship, street, and postal code
Get your free API key at isvalid.dev. The free tier includes 100 calls per day with no credit card required.
Full parameter reference and response schema: KRS Validation API docs →
5. Node.js code example
Using the @isvalid-dev/sdk package or the built-in fetch API (Node.js 18+):
// krs-validator.mjs import { createClient } from '@isvalid-dev/sdk'; const iv = createClient({ apiKey: process.env.ISVALID_API_KEY }); // ── Basic validation ──────────────────────────────────────────────────────── const result = await iv.pl.krs('0000896246'); if (!result.valid) { console.log('Invalid KRS number'); } else { console.log('KRS:', result.number); // "0000896246" } // ── With government registry lookup ───────────────────────────────────────── const detailed = await iv.pl.krs('0000896246', { lookup: true }); if (detailed.valid && detailed.krs?.found) { console.log('Name :', detailed.krs.name); console.log('Registry :', detailed.krs.registry); // "P" or "S" console.log('NIP :', detailed.krs.nip); console.log('REGON :', detailed.krs.regon); console.log('City :', detailed.krs.address.city); console.log('OPP :', detailed.krs.hasOppStatus); }
lookup parameter is optional. Use it when you need the entity's name, NIP, REGON, or address. Omit it for fast format-only validation.6. cURL examples
Basic format validation:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/pl/krs?value=0000896246"
With government registry lookup:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/pl/krs?value=0000896246&lookup=true"
7. Understanding the response
Valid KRS (basic)
{ "valid": true, "number": "0000896246" }
Valid KRS (with lookup)
{ "valid": true, "number": "0000896246", "krs": { "checked": true, "found": true, "krs": "0000896246", "registry": "P", "name": "CREACT.DEV SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ", "legalForm": "SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ", "nip": "5252859428", "regon": "388770013", "hasOppStatus": false, "registeredAt": "2021-04-21", "dataAsOf": "2026-01-15", "lastEntryAt": "2026-01-14", "address": { "city": "WARSZAWA", "voivodeship": "MAZOWIECKIE", "street": "UL. ŚWIĘTOKRZYSKA", "houseNumber": "30", "flatNumber": "63", "postalCode": "00-116", "country": "POLSKA", "website": "HTTPS://CREACT.DEV/" } } }
Invalid KRS
{ "valid": false }
| Field | Type | Description |
|---|---|---|
| valid | boolean | Whether the KRS number passed format validation |
| number | string | The zero-padded 10-digit KRS number. Only present when valid: true |
| krs.registry | string | "P" (Entrepreneurs) or "S" (Associations) |
| krs.name | string | Full legal name of the entity |
| krs.legalForm | string | Legal form (e.g. Sp. z o.o., S.A., Fundacja) |
| krs.nip | string | NIP (tax identification number) |
| krs.regon | string | REGON (statistical registry number) |
| krs.hasOppStatus | boolean | Whether the entity has OPP (public benefit organisation) status |
| krs.registeredAt | string | Date when the entity was first registered in KRS (ISO 8601) |
| krs.dataAsOf | string | Date of the data snapshot from the registry |
| krs.lastEntryAt | string | Date of the most recent entry/modification in the registry |
| krs.address | object | Registered address with city, voivodeship, street, houseNumber, flatNumber, postalCode, country, and website |
8. Edge cases to handle
(a) Leading zeros
KRS numbers are zero-padded to 10 digits. A company registered early might have a KRS like 0000028860. Do not store KRS numbers as integers — use strings to preserve leading zeros. The API accepts both 28860 and 0000028860 and normalises the value.
// WRONG — loses leading zeros const krs = Number('0000028860'); // 28860 // CORRECT — preserve as string const krs = '0000028860';
(b) Register P vs Register S
The registry field in the lookup response tells you whether the entity is in the Entrepreneurs register (P) or the Associations register (S). This distinction matters for compliance — a foundation (register S) has different legal obligations than a commercial company (register P).
const result = await iv.pl.krs('0000896246', { lookup: true }); if (result.valid && result.krs?.found) { if (result.krs.registry === 'P') { console.log('Commercial entity — standard B2B flow'); } else if (result.krs.registry === 'S') { console.log('Association/foundation — verify OPP status'); } }
(c) OPP status (public benefit organisations)
Entities with hasOppStatus: true are registered as Organisations of Public Benefit (Organizacja Pozytku Publicznego). These entities can receive 1.5% of personal income tax from taxpayers. Check this field when building donation platforms or tax-deduction workflows.
const result = await iv.pl.krs('0000896246', { lookup: true }); if (result.valid && result.krs?.found && result.krs.hasOppStatus) { console.log('This entity can receive 1.5% tax donations'); }
(d) Dissolved companies
A KRS number that passes format validation may belong to a dissolved or deregistered entity. When the lookup returns a result, check whether the entity is still active. The lastEntryAt and dataAsOf fields help you determine whether the data is current.
const result = await iv.pl.krs('0000896246', { lookup: true }); if (result.valid && result.krs) { if (!result.krs.found) { console.log('KRS number not found — entity may be dissolved'); } else { console.log('Last entry:', result.krs.lastEntryAt); console.log('Data as of:', result.krs.dataAsOf); } }
(e) Cross-referencing with REGON and NIP
The KRS lookup returns both nip and regon fields. Use these to cross-reference with data provided by the entity. If a business partner gives you a KRS, NIP, and REGON, you can validate all three in a single KRS lookup and check they match.
const result = await iv.pl.krs('0000896246', { lookup: true }); if (result.valid && result.krs?.found) { const expectedNip = '5252859428'; const expectedRegon = '388770013'; if (result.krs.nip !== expectedNip) { console.error('NIP mismatch!'); } if (result.krs.regon !== expectedRegon) { console.error('REGON mismatch!'); } }
9. Summary
See also
Validate KRS numbers instantly
Free tier includes 100 API calls per day. No credit card required. Format validation and optional government registry lookup included.