DEV Community

Piotr Kaplon
Piotr Kaplon

Posted on

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

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

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"
}
Enter fullscreen mode Exit fullscreen mode
  1. Click "Start"
  2. Wait ~30 seconds
  3. 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
const financials = await getPolishCompanyFinancials('0000023302');
console.log(financials);
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

Method 3: Using cURL

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

# Start the Actor and wait for results
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"}'
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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' });
Enter fullscreen mode Exit fullscreen mode

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

Understanding the Output

Parsed Financial Metrics

Field Polish Name Description
totalAssets Aktywa razem Total assets
fixedAssets Aktywa trwałe Fixed/non-current assets
currentAssets Aktywa obrotowe Current assets
equity Kapitał własny Shareholders' equity
revenue Przychody Revenue from sales
operatingProfit Zysk operacyjny Operating profit
netProfit Zysk netto Net profit

Raw Data Access

For custom parsing, the full XML/XHTML file is available in rawXml:

const { rawXml, fileFormat } = financials;

if (fileFormat === 'xml') {
    // Parse Polish Accounting Standards format
    const parser = new DOMParser();
    const doc = parser.parseFromString(rawXml, 'text/xml');
    // Custom extraction...
}
Enter fullscreen mode Exit fullscreen mode

Real-World Use Cases

1. Competitor Analysis Dashboard

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

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

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

2. 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 };
}
Enter fullscreen mode Exit fullscreen mode

3. 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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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.

Links:


Have questions? Drop them in the comments!

Top comments (0)