How to Extract Polish Company Financial Data with a Single API Call

Published: (December 29, 2025 at 09:20 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Piotr Kaplon

Introduction

Ever needed financial data on a Polish company? Whether you’re building a fintech app, doing competitor analysis, or automating due diligence, accessing data from Poland’s National Court Register (KRS) can be… painful.

In this tutorial, I’ll show you how to get balance sheets, income statements, and key financial metrics from any Polish company in under 30 seconds.

The Problem

Poland requires all companies to submit annual financial statements to the eKRS portal. This data is public, but:

  • No official API exists
  • Multiple page navigations required
  • Files come in XML or XHTML format

Complex Polish accounting schemas (AktywaRazem, KapitalWlasny, ZyskNetto…)

  • Different schemas for different accounting standards (UoR vs IFRS)

Building a scraper from scratch takes 20‑40 hours. But that’s just step one — then you need to parse the XML, which means learning Polish accounting terminology and handling multiple schema versions.

The Solution

We’ll use the Poland KRS Financial Scraper Actor on Apify. It handles all the complexity — including XML parsing — and returns structured JSON with financial metrics ready to use.

Key benefit: You get totalAssets, equity, revenue, netProfit, etc. directly in JSON — no XML parsing required on your end.

Prerequisites

  • Free Apify account (sign up here)
  • API token (found in Apify Console → Settings → Integrations)
  • A Polish company’s NIP (tax ID) or KRS number

Method 1: Using the Apify Console (No Code)

The simplest way to test:

  1. Go to the Actor page.

  2. Enter input:

    {
      "krs": "0000023302"
    }
  3. Click Start.

  4. Wait ~30 seconds.

  5. View results in the Dataset tab.

Method 2: Using the API (JavaScript/Node.js)

For integration into your applications:

const Apify = require('apify-client');

const client = new Apify.ApifyClient({
    token: 'YOUR_API_TOKEN',
});

async function getPolishCompanyFinancials(krsNumber) {
    // Start the Actor
    const run = await client.actor('minute_contest/poland-krs-financial-scraper').call({
        krs: krsNumber,
    });

    // Get results from dataset
    const { items } = await client.dataset(run.defaultDatasetId).listItems();

    return items[0];
}

// Example usage
(async) => {
    const financials = await getPolishCompanyFinancials('0000023302');
    console.log(financials);
})();

Sample output

{
  "krs": "0000023302",
  "year": 2024,
  "fileName": "Sprawozdanie_finansowe_2024.xml",
  "fileFormat": "xml",
  "financials": {
    "totalAssets": 54850000000,
    "equity": 32100000000,
    "fixedAssets": 42100000000,
    "currentAssets": 12750000000,
    "revenue": 33500000000,
    "operatingProfit": 4200000000,
    "netProfit": 2850000000
  },
  "success": true
}

Method 3: Using cURL

For quick command‑line testing or integration with any language:

curl -X POST "https://api.apify.com/v2/acts/minute_contest~poland-krs-financial-scraper/run-sync-get-dataset-items" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{"krs": "0000023302"}'

Method 4: Using Python

from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

def get_polish_company_financials(krs_number):
    run_input = {"krs": krs_number}
    run = client.actor("minute_contest/poland-krs-financial-scraper").call(run_input=run_input)
    items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
    return items[0] if items else None

# Example
financials = get_polish_company_financials("0000023302")
print(f"Total Assets: {financials['financials']['totalAssets']:,} PLN")
print(f"Net Profit:   {financials['financials']['netProfit']:,} PLN")

Using NIP Instead of KRS

Don’t have the KRS number? Use the company’s NIP (tax ID) instead:

const financials = await getPolishCompanyFinancials({ nip: '8992736629' });

The Actor will automatically look up the KRS number from the NIP.

Understanding the Output

Parsed Financial Metrics

FieldPolish NameDescription
totalAssetsAktywa razemTotal assets
fixedAssetsAktywa trwałeFixed / non‑current assets
currentAssetsAktywa obrotoweCurrent assets
equityKapitał własnyShareholders’ equity
revenuePrzychodyRevenue from sales
operatingProfitZysk operacyjnyOperating profit
netProfitZysk nettoNet profit

Raw Data Access

If you need custom parsing, the full XML/XHTML file is available in rawXml:

const { rawXml, fileFormat } = financials;

if (fileFormat === 'xml') {
    const parser = new DOMParser();
    const doc = parser.parseFromString(rawXml, 'text/xml');
    // Custom extraction...
}

Real‑World Use Cases

Competitor‑Analysis Dashboard

const competitors = ['0000023302', '0000012345', '0000067890'];

const results = await Promise.all(
    competitors.map(krs => getPolishCompanyFinancials(krs))
);

console.table(results.map(r => ({
    krs: r.krs,
    revenue: r.financials.revenue,
    netProfit: r.financials.netProfit,
})));

Bulk Retrieval Example

const results = await Promise.all(
    krsList.map(krs => getPolishCompanyFinancials(krs))
);

// Compare metrics
results.forEach(company => {
    console.log(`KRS ${company.krs}: Revenue ${company.financials.revenue}`);
});

Automated Due Diligence

async function dueDiligenceCheck(nip) {
    const financials = await getPolishCompanyFinancials({ nip });

    const checks = {
        hasPositiveEquity: financials.financials.equity > 0,
        isProfitable: financials.financials.netProfit > 0,
        currentRatio:
            financials.financials.currentAssets /
            (financials.financials.totalAssets - financials.financials.equity)
    };

    return { financials, checks };
}

Bulk Data Collection

const companies = readCSV('polish_companies.csv'); // List of KRS numbers

for (const krs of companies) {
    const data = await getPolishCompanyFinancials(krs);
    await saveToDatabase(data);
    await sleep(1000); // Rate limiting
}

Pricing

The Actor uses pay‑per‑result pricing:

  • ~$0.03 per successful extraction
  • No subscription required
  • Free tier available for testing

Error Handling

const result = await getPolishCompanyFinancials('0000023302');

if (!result.success) {
    console.error(`Error: ${result.error}`);
    // Common errors:
    // - "Company not found" – Invalid KRS number
    // - "No financial statements" – Company hasn't filed yet
    // - "Multiple formats" – Handle XHTML separately
}

Conclusion

Accessing Polish company financial data doesn’t have to be complicated. With a single API call, you can get structured financial metrics ready for analysis.

Have questions? Drop them in the comments!

Back to Blog

Related posts

Read more »