DEV Community

Cover image for Extracting Financial Metrics for 1,000 Finnish Oy Companies
Crawler Bros
Crawler Bros

Posted on Fully Autonomous

Extracting Financial Metrics for 1,000 Finnish Oy Companies

Screening business partners or sales targets in Nordic markets often stalls when standard B2B directories omit balance sheet information. While basic directory platforms only provide business names, postal addresses, and switchboard numbers, Finnish enterprise profiles registered on Finder.fi (managed by Fonecta) include data direct from the Finnish Patent and Registration Office (PRH) and Statistics Finland.

Extracting structured data from Finder.fi Business Directory Scraper solves this by yielding trade registry dates, signing authorities, official industry classification codes, and multi-year financial statements for Finnish incorporated entities (Oy).

Navigating Finnish Registry Taxonomies and Financial Units

Automating data collection from Finder.fi requires handling two structural specifics unique to the Finnish market: standardized industry codes and reported monetary scales.

First, Finder.fi exposes two parallel categorizations for a company:

  • category / categories[]: Finder.fi's internal consumer-facing browsing taxonomy (such as Ravintola or IT-konsultointi).
  • industryCode / industryName: The official Finnish TOL (Toimialaluokitus) industry classification code and description sourced from Statistics Finland.

Second, all monetary values published under the financials[] array and top-level summaries are formatted in thousands of euros (KEur), matching the platform's native reporting structure. If an item reports latestTurnoverKEur: 2018, the company's true revenue is €2,018,000.

Sourcing Official Registry Milestones

Beyond balance sheets, the platform aggregates public registration timelines from the PRH. The scraper captures these exact dates as separate string attributes:

  • tradeRegisterDate: Initial registration in the Finnish Trade Register.
  • vatRegisterDate: Registration date for value-added tax liabilities.
  • employerRegisterDate: Registration as an official employer.
  • prepaymentRegisterDate: Entry into the prepayment register (Ennakkonperintärekisteri), essential for verifying tax prepayment status before paying invoices to Finnish subcontractors.
  • businessStatusCode: The raw registry code sourced from the PRH, where a value of "A" indicates an active status.

The output record also extracts signingAuthority, which details the official statutory rules governing who can sign agreements on behalf of the legal entity (for example, "Board member alone").

Execution Modes and Search Parameters

The scraper operates in two distinct operational modes via the mode parameter: search and byUrl.

Mode 1: Search Queries

To mine targeted business lists by geography and trade, supply the category or customQuery alongside a city parameter representing one of the 309 Finnish municipalities.

{
  "mode": "search",
  "category": "Ravintola",
  "city": "Helsinki",
  "maxItems": 100
}
Enter fullscreen mode Exit fullscreen mode

If you need a niche term outside the predefined category taxonomy, pass an empty string to category and supply your search terms directly through customQuery.

{
  "mode": "search",
  "category": "",
  "customQuery": "tilitoimisto",
  "city": "Tampere",
  "maxItems": 50
}
Enter fullscreen mode Exit fullscreen mode

Mode 2: Direct Target Profiling

When you already maintain a list of Finnish business IDs or target links, set mode to byUrl. The businessUrls array accepts full Finder.fi profile URLs or bare internal numeric office IDs.

{
  "mode": "byUrl",
  "businessUrls": [
    "https://www.finder.fi/Ravintola/Ravintola+Ragu/Helsinki/yhteystiedot/2701900",
    "172446"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Finder.fi resolves profiles based on the trailing numeric office ID alone, automatically bypassing path drift or legacy company name changes in the URL structure.

Parsing Output Financial Objects with Python

When processed through the search or URL lookups, the scraper returns JSON structures. The following snippet illustrates how to extract historical revenue trends and verify corporate registration metrics using Python.

import json

# Sample item returned from the Apify dataset
record = {
    "name": "Esimerkki Oy",
    "businessId": "1234567-8",
    "businessStatusCode": "A",
    "industryCode": "62010",
    "industryName": "Ohjelmistojen suunnittelu ja valmistus",
    "latestTurnoverKEur": 2500,
    "financials": [
        {
            "fiscalYear": "2023",
            "turnoverKEur": 2500,
            "operatingProfitKEur": 350,
            "numberOfEmployees": 18,
            "solvencyPercent": 65.4
        },
        {
            "fiscalYear": "2022",
            "turnoverKEur": 1900,
            "operatingProfitKEur": 210,
            "numberOfEmployees": 14,
            "solvencyPercent": 58.2
        }
    ]
}

def parse_company_metrics(item):
    name = item.get("name")
    y_tunnus = item.get("businessId")

    # Calculate raw euro turnover from KEur
    turnover_keur = item.get("latestTurnoverKEur")
    turnover_eur = turnover_keur * 1000 if turnover_keur is not None else None

    print(f"Company: {name} ({y_tunnus})")
    if turnover_eur:
        print(f"Latest Turnover: €{turnover_eur:,}")

    # Process historical performance
    for year in item.get("financials", []):
        year_name = year.get("fiscalYear")
        margin = year.get("operatingProfitKEur")
        employees = year.get("numberOfEmployees")
        print(f"  [{year_name}] Profit: €{margin * 1000 if margin else 0:,} | Staff: {employees}")

parse_company_metrics(record)
Enter fullscreen mode Exit fullscreen mode

Running the Scraper via the Apify API

To configure an automated workflow using Python, invoke the run using the Apify API client.

Step 1: Install the Client Library

pip install apify-client
Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize and Trigger the Run

Pass your input configuration directly into the actor execution call.

from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run_input = {
    "mode": "search",
    "category": "",
    "customQuery": "LVI-asennus",
    "city": "Oulu",
    "maxItems": 50
}

# Execute the Finder.fi scraper actor
run = client.actor("crawlerbros/finder-fi-scraper").call(run_input=run_input)

# Fetch dataset results
dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in dataset_items:
    print(item.get("name"), item.get("phone"), item.get("latestTurnoverKEur"))
Enter fullscreen mode Exit fullscreen mode

Event Cost Structure

This actor uses Apify's Event-Based Pricing model. Executions are charged strictly per event:

  • Actor Start (apify-actor-start): $0.005 per GB of memory allocated to the run (charged once upon start).
  • Result (apify-default-dataset-item): $0.005 per single scraped result record returned to the default dataset.

Volume-tier pricing automatically lowers the per-result event price for higher usage volumes:

  • FREE: $0.005 per result
  • BRONZE: $0.00433 per result
  • SILVER: $0.00367 per result
  • GOLD / PLATINUM / DIAMOND: $0.003 per result

Extracting 1,000 completed business records on a standard tier translates to 1,000 result events ($5.00) plus the single memory-scaled start event.

Data Limitations

This tool does not return financial statements for sole proprietorships (Toiminimi) or small non-profit associations, as Finnish law does not mandate that these business entities publish public balance sheet accounts to the trade register. For these listings, contact details and municipality registers are emitted, but the financials[] array is omitted from the dataset.


If you want to reproduce this, the Actor is Finder.fi Business Directory Scraper. Read its input schema before the first run -- most failed runs are a missing required field, not a block.

Prices quoted above are this Actor's published pay-per-event rates on the Apify Store, read from the Apify platform API on 2026-09-20. Check the Actor page for the current rates.

Top comments (0)