# Finland Company Register (PRH YTJ) (`cliqtomedia/finland-ytj-company-register`) Actor

Look up Finnish companies by Business ID (Y-tunnus) or search by name, city, company form or business line. Official PRH YTJ open data: names and name history, status, form, TOL line, register entries, addresses.

- **URL**: https://apify.com/cliqtomedia/finland-ytj-company-register.md
- **Developed by:** [Cliqto Media](https://apify.com/cliqtomedia) (community)
- **Categories:** Business, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 company records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Finland Company Register (PRH YTJ) looks up Finnish companies in the official YTJ open data register of the Finnish Patent and Registration Office (PRH) and the Finnish Tax Administration. Add Finnish Business IDs (Y-tunnus), or search by company name, town, company form, business line, postcode or registration date. You get one clean row per company: name and full name history, company form, main business line, register entries, addresses, website and a clear status: active, ceased, bankrupt or not found.

It is made for KYB checks, supplier onboarding, CRM cleaning and B2B lists in Finland. No login and no API key are needed. A run with three Business IDs finishes in a few seconds and costs about $0.014.

![Finland Company Register: Business IDs in, official YTJ company record with status, company form, main business line, register entries and name history out](https://api.apify.com/v2/key-value-stores/A9Av3J1kuF2FsjZkR/records/README-BANNER-20261013.png)

### Contents

- [What it does](#what-it-does)
- [Quick start](#quick-start)
- [Use cases](#use-cases)
- [Input](#input)
- [Output](#output)
- [Pricing](#pricing)
- [Limits](#limits)
- [API and integrations](#api-and-integrations)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Data source and licence](#data-source-and-licence)
- [Related Actors](#related-actors)
- [Support](#support)

### What it does

The Actor reads the public [YTJ open data API v3](https://avoindata.prh.fi/en/ytj/swagger-ui) live on each run. It has two modes:

- **Business ID lookup.** Each Business ID is an exact match. The Actor checks the check digit first. A wrong ID gives an `invalid_input` row, and a valid ID that is not in the register gives a `not_found` row, so no input is lost. The same ID written twice is looked up once.
- **Search.** Filters by company name, town, company form, main business line, postcode and registration dates. The source decides the order of results.

#### Good fit

- Check that a Finnish supplier or customer exists and is still active (KYB, onboarding).
- See all names of a company: current, previous, parallel (Swedish or English) and auxiliary names, with dates.
- Fill CRM records with the official name, company form, TOL 2008 business line, address and website.
- Build a list of companies by town, form, business line or registration date.

#### Not a fit

- Email addresses and phone numbers. The register does not publish them, and the Actor does not add them.
- Directors, owners, beneficial owners or financial statements. They are not in this open data.
- Proof that a VAT number is valid on a date. `inVatRegister` shows a VAT register entry in YTJ. For a VAT check, use the EU VIES service.
- Private traders (sole proprietors). The open data covers companies registered or pending in the Trade Register, not private traders.
- Norwegian, Swedish or other Nordic companies. This Actor covers Finland only.

### Quick start

1. Open the **Input** tab. The form already has three Business IDs: Nokia Oyj (active), Nokia Networks Oy (ceased) and Primera Holidays Oy (bankrupt).
2. Click **Start**.
3. Open the **Companies** view in the Output tab. Check `name`, `isActive`, `tradeRegisterStatus` and `currentSituations`.
4. Replace the IDs with your own list (up to 100), or clear the list and use the search filters.

Expected result: three `complete` company rows in a few seconds.

### Use cases

| Buyer job | Input | Key fields |
| --- | --- | --- |
| Verify a company (KYB) | `businessIds` | `status`, `isActive`, `tradeRegisterStatus`, `currentSituations`, `endDate` |
| Match old invoices or contracts to a company | `businessIds` or `name` | `names`, `previousNames`, `parallelNames`, `auxiliaryNames` |
| Clean CRM records | `businessIds` | `name`, `companyForm`, `mainBusinessLine`, `streetAddress`, `website` |
| Prospect list by town and activity | `location` + `mainBusinessLine` | `businessId`, `name`, `registrationDate`, `postalAddress` |
| New companies in a period | `registrationDateFrom` / `registrationDateTo` + filters | `registrationDate`, `companyForm`, `streetAddress` |

### Input

Use **either** `businessIds` **or** search filters in one run. A run with both is rejected with `INVALID_INPUT`. Several filters in one search are combined (all must match).

| Field | Type | Default | Allowed values | What it does |
| --- | --- | --- | --- | --- |
| `businessIds` | array of strings | none (form example: 3 IDs) | up to 100 | Exact lookup. Accepts `0112038-9`, `01120389`, the old six-digit form `112038-9` and FI VAT numbers like `FI01120389`. |
| `name` | string | none | 2–200 characters | Search by company name, for example `nokia`. |
| `location` | string | none | up to 100 characters | Town or city of the company address, for example `Helsinki`. |
| `companyForm` | string | `""` (any form) | 27 YTJ form codes, such as `OY`, `OYJ`, `KY`, `AY`, `OK`, `ASY`, `SÄÄ` | Company form, for example `OY` (limited company). |
| `mainBusinessLine` | string | none | up to 200 characters | TOL 2008 code such as `62010`, or text from its description such as `software`. |
| `postCode` | string | none | 5 digits | Finnish postcode, for example `00100`. |
| `registrationDateFrom` | string | none | `YYYY-MM-DD` | Companies registered on or after this date. |
| `registrationDateTo` | string | none | `YYYY-MM-DD` | Companies registered on or before this date. |
| `maxResults` | integer | 100 | 1–5000 | Search mode only. Maximum companies in a search. Each company row is charged. |
| `language` | string | `en` | `en`, `fi`, `sv` | Language of labels: company form, statuses, business line, register names and city. A value the source has only in Finnish stays in Finnish. |

Recommendation: for KYB, use Business IDs. A search is a list builder, not a verified match.

#### Input examples

Lookup:

```json
{
  "businessIds": ["0112038-9", "0101120-3", "0211270-0"]
}
```

Software companies in Tampere, labels in Finnish:

```json
{
  "location": "Tampere",
  "mainBusinessLine": "62010",
  "maxResults": 200,
  "language": "fi"
}
```

Public limited companies registered in 2024:

```json
{
  "companyForm": "OYJ",
  "registrationDateFrom": "2024-01-01",
  "registrationDateTo": "2024-12-31"
}
```

### Output

One Dataset row per company or input. Use the **Companies** view for a flat table. The key-value store has a `RUN_SUMMARY` record with the run status and counts.

#### Row status

| `status` | Meaning | Charged |
| --- | --- | --- |
| `complete` | The company was found. Fields are as complete as the register allows. A ceased or bankrupt company is `complete` too: read `isActive`. | company price |
| `not_found` | A valid Business ID that is not in the YTJ open data: unknown, a private trader, or too new (the source updates once a day). | not-found price |
| `invalid_input` | Not a valid Business ID (format or check digit). `statusReason` says why and shows the expected check digit. | no |
| `error` | The source failed or the run stopped before this ID. `statusReason` starts with a code such as `RATE_LIMITED` or `SOURCE_UNAVAILABLE`. | no |

#### Company fields

| Field | Type | Meaning | Example |
| --- | --- | --- | --- |
| `inputBusinessId` | string or null | Your value as entered; `null` in search mode | `"01120389"` |
| `status`, `statusReason` | string, string or null | Row result, see above | `"complete"`, `null` |
| `businessId` | string | Business ID with the leading zero and hyphen | `"0112038-9"` |
| `name` | string or null | Current company name | `"Nokia Oyj"` |
| `isActive` | boolean or null | `true` when the Business ID is valid, the company has no end date, is not ceased in the Trade Register and is not in bankruptcy or liquidation. A start-up that is not yet in the Trade Register is also `true` | `true` |
| `businessIdStatus`, `businessIdStatusCode` | string or null | Status of the Business ID | `"Valid"`, `"2"` |
| `tradeRegisterStatus`, `tradeRegisterStatusCode` | string or null | Trade Register status | `"Registered"`, `"1"` |
| `currentSituations` | array of strings | Current situation codes: `KONK` bankruptcy, `SELTILA` liquidation, `SANE` restructuring | `["KONK"]` |
| `companyForm`, `companyFormCode`, `companyFormAbbreviation` | string or null | Current company form (or the last known form of an ended company) | `"Public limited company"`, `"17"`, `"OYJ"` |
| `mainBusinessLineCode`, `mainBusinessLine`, `mainBusinessLineCodeSet` | string or null | Main business line, TOL 2008 | `"70100"`, `"Activities of head offices"`, `"TOIMI4"` |
| `website` | string or null | Website as registered | `"www.nokia.com"` |
| `registrationDate`, `endDate` | string or null | Company registration and end dates, `YYYY-MM-DD` | `"1896-12-19"`, `null` |
| `businessIdRegistrationDate` | string or null | Date the Business ID was given | `"1978-03-15"` |
| `euId` | string or null | EUID used in the EU business registers network | `"FIFPRO.0112038-9"` |
| `inTradeRegister`, `inVatRegister`, `inEmployerRegister`, `inPrepaymentRegister` | boolean or null | Current entry in the register. `inVatRegister` is a register entry, not a VAT validity check | `true` |
| `streetAddress`, `postalAddress` | object or null | `street`, `buildingNumber`, `entrance`, `apartmentNumber`, `postOfficeBox`, `co`, `postCode`, `city`, `cityFi`, `citySv`, `municipalityCode`, `country`, `freeAddressLine`, `formatted`, `registrationDate` | `{"formatted": "Karakaari 7, 02610 ESPOO", "citySv": "ESBO"}` |
| `previousNames`, `parallelNames`, `auxiliaryNames` | array of strings | Name lists by type | `["Oy Nokia Ab"]` |
| `names` | array of objects | Every name with `name`, `type`, `typeCode`, `registrationDate`, `endDate`, `current` | see example |
| `companyForms` | array of objects | Form history with dates | |
| `situations` | array of objects | Bankruptcy, liquidation and restructuring history with dates | |
| `registeredEntries` | array of objects | Register entries with `register`, `status`, `registrationDate`, `endDate`, `authority`, `current` | |
| `lastModified` | string or null | When the source last changed this company record | `"2026-08-19T10:04:06"` |
| `ytjUrl` | string or null | Public company page on tietopalvelu.ytj.fi | |
| `sourceUrl`, `provider`, `licence`, `fetchedAt` | string | Provenance: the API request, PRH and the Tax Administration, CC BY 4.0, and our read time | |

`null` means the source has no value. It never means zero or `false`.

#### Output example

A trimmed row:

```json
{
  "inputBusinessId": "0112038-9",
  "status": "complete",
  "businessId": "0112038-9",
  "name": "Nokia Oyj",
  "isActive": true,
  "tradeRegisterStatus": "Registered",
  "companyFormAbbreviation": "OYJ",
  "mainBusinessLineCode": "70100",
  "mainBusinessLine": "Activities of head offices",
  "website": "www.nokia.com",
  "registrationDate": "1896-12-19",
  "inVatRegister": true,
  "currentSituations": [],
  "streetAddress": { "formatted": "Karakaari 7, 02610 ESPOO", "postCode": "02610", "city": "ESPOO", "citySv": "ESBO" },
  "previousNames": ["Oy Nokia Ab"],
  "parallelNames": ["Nokia Abp", "Nokia Corporation"],
  "names": [
    { "name": "Oy Nokia Ab", "type": "Company name", "typeCode": "1", "registrationDate": "1966-06-10", "endDate": "1997-08-31", "current": false }
  ],
  "lastModified": "2026-08-19T10:04:06",
  "ytjUrl": "https://tietopalvelu.ytj.fi/yritys/0112038-9",
  "licence": "CC BY 4.0",
  "fetchedAt": "2026-10-12T09:21:05.000Z"
}
```

#### Run summary

`RUN_SUMMARY.status` is one of `COMPLETE`, `PARTIAL`, `NOT_FOUND` (no ID was found), `NO_RESULTS` (empty search), `CAPPED` (stopped at your cost limit or at the internal limit of 240 seconds or 700 requests), `ERROR`, `INVALID_INPUT` (the run fails; no row is charged) or `CANCELLED`. `counts` shows rows by status and charged rows. `search.totalResults` shows how many companies the source matched. `search.resultsCappedByMaxResults: true` only means the search had more matches than your `maxResults`; the run status stays `COMPLETE`. `warnings` explains anything unusual.

### Pricing

Pay per event. Platform usage is included.

| Event | Price | When |
| --- | ---: | --- |
| Actor start | $0.002 | Once per run (per GB of memory; the default 256 MB counts once) |
| Company record | $0.004 (lower on higher Apify plans) | Each `complete` company row |
| Not-found lookup | $0.001 | Each `not_found` row |

`invalid_input` and `error` rows are free. An empty search costs only the start.

| Run | Example cost |
| --- | ---: |
| 3 Business IDs (form example) | $0.014 |
| 10 Business IDs | $0.042 |
| 100 Business IDs | $0.402 |
| 100 unknown Business IDs | $0.102 |
| Search, 1,000 companies | $4.002 |
| Search, 5,000 companies | $20.002 |

Set a maximum cost per run in the run options to cap your spend. The Actor stops before a paid row that does not fit and reports `CAPPED`.

### Limits

- Up to 100 Business IDs per run, or up to 5,000 companies per search. A town like Helsinki has about 90,000 companies, so add filters to narrow a search.
- The Actor sends about one request per second, because the source blocks fast clients for a while. 100 Business IDs take about 100 seconds; a 5,000-company search took about 90 seconds in our test.
- The source updates once a day. A company registered today can be `not_found` until the next update.
- The internal time budget is 240 seconds and 700 requests. When a run reaches it, the run stops with `CAPPED` and the rows found so far are kept.
- If the source fails or blocks the run, the Actor stops after two failed requests in a row. The rest of the IDs get free `error` rows and the run is `PARTIAL` or `ERROR`. Run those IDs again later.
- Search pages can hold fewer than 100 companies. If the source serves fewer unique companies than it reports, `RUN_SUMMARY.warnings` says so.

### API and integrations

Start a run with the same JSON input through the Apify API (`POST /v2/acts/cliqtomedia~finland-ytj-company-register/runs`), then read the Dataset. Export to CSV, Excel or JSON, or connect the run to other tools with the usual Apify integrations. For CSV, use the **Companies** view. Join rows on `businessId`.

There is no built-in monitoring mode. To re-check the same list regularly, create an Apify schedule for a saved task and compare `isActive`, `currentSituations` or `lastModified` between runs.

#### Use with AI agents (MCP)

AI agents can call this Actor through the Apify MCP server: add `https://mcp.apify.com?tools=cliqtomedia/finland-ytj-company-register` to your MCP client (Claude, Cursor, VS Code and others). The MCP server needs your Apify account (OAuth sign-in or an Apify API token); the data source itself needs no key. The agent builds the input from the input schema. The smallest useful input:

```json
{ "businessIds": ["0112038-9"] }
```

Key output fields for an agent: `status`, `name`, `isActive`, `tradeRegisterStatus`, `currentSituations`, `companyForm`, `mainBusinessLine`, `streetAddress.formatted`. A call with 10 IDs finishes in about 15 seconds and costs about $0.042. A run with 100 IDs takes about 100 seconds and can outlast the MCP call wait, so the agent may need to poll the run for its result. An agent should verify a company by Business ID, not by a search result.

### Troubleshooting

| Symptom | Check | Action |
| --- | --- | --- |
| `invalid_input` for an ID | `statusReason` | Usually a typo. The message shows the expected check digit. |
| `not_found` for a real company | `statusReason` | A private trader is not in this open data. A very new company appears after the next daily update. |
| `isActive: false` for a registered company | `currentSituations`, `situations` | `KONK` (bankruptcy) or `SELTILA` (liquidation) is in progress. |
| Labels in Finnish with `language: "en"` | the field | The source has no English text for that value. |
| `error` rows with `RATE_LIMITED` | `RUN_SUMMARY.http.rateLimited` | The source blocked requests for a while. Run the failed IDs again later. |
| `INVALID_INPUT` | `RUN_SUMMARY.message` | Common causes: Business IDs and search filters in one run, no input at all, a name shorter than 2 characters, a bad postcode or date. |

### FAQ

#### Do I need an API key or a Finnish account?

No. The source is open and free. You only need your Apify account.

#### Does a VAT register entry mean the VAT number is valid today?

No. `inVatRegister` shows that YTJ has a current VAT register entry for the company. To check a VAT number on a date, use the EU VIES service.

#### Why are there no emails or phone numbers?

PRH open data does not publish them. The Actor gives only what the register publishes.

#### How fresh is the data?

Each run reads the source live. The source updates once a day. Each row has `fetchedAt` (our read time) and `lastModified` (when the source last changed the record).

#### Can I use the data commercially?

Yes. The data is published under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which allows commercial reuse with attribution. See below.

### Data source and licence

Data: [PRH open data, YTJ API v3](https://avoindata.prh.fi/en/ytj/swagger-ui), Finnish Patent and Registration Office (PRH) and Finnish Tax Administration, under the [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/) licence. When you reuse the data, name the source: "Source: Finnish Patent and Registration Office (PRH) and Finnish Tax Administration, YTJ open data, CC BY 4.0". The Actor changes the format (flat fields, labels by language) but not the values. This Actor is independent and not endorsed by PRH, the Finnish Tax Administration or the [YTJ service](https://ytj.fi/en/index/opendata.html).

### Related Actors

- [France Company & SIRET Search](https://apify.com/cliqtomedia/france-sirene-company-search): French companies from the official Sirene data.
- [Norway Company Register (Brreg) & Updates](https://apify.com/cliqtomedia/norway-brreg-company-register): Norwegian companies from Brønnøysund.

### Support

Use the **Issues** tab of this Actor. Add the run ID, the mode (Business IDs or search) and the `statusReason` you saw. Do not send API tokens or private data.

# Changelog

This Actor's version history is a separate document: https://apify.com/cliqtomedia/finland-ytj-company-register/changelog.md

# Actor input Schema

## `businessIds` (type: `array`):

Exact lookup of up to 100 Finnish Business IDs, e.g. 0112038-9. Also accepts 01120389, the old six-digit form and FI VAT numbers (FI01120389). Wrong check digits are reported as invalid_input (free). Duplicates are looked up once. Leave empty to run a search instead.

## `name` (type: `string`):

Search filter, not combinable with Business IDs. Matches current and earlier names, at least 2 characters, e.g. nokia.

## `location` (type: `string`):

Search filter: town/city of the registered address, e.g. Helsinki, Espoo or Tampere.

## `companyForm` (type: `string`):

Search filter: company form, e.g. OY (limited company) or OYJ (public limited company).

## `mainBusinessLine` (type: `string`):

Search filter: TOL 2008 code (e.g. 62010) or text from its description (e.g. software).

## `postCode` (type: `string`):

Search filter: 5-digit Finnish postcode, e.g. 00100.

## `registrationDateFrom` (type: `string`):

Search filter: company registration date from (inclusive), YYYY-MM-DD.

## `registrationDateTo` (type: `string`):

Search filter: company registration date to (inclusive), YYYY-MM-DD.

## `maxResults` (type: `integer`):

Search mode only. Maximum companies returned, 1–5000. Default 100. Each company row is charged.

## `language` (type: `string`):

Language of labels (company form, statuses, business line, city). Values the source has only in Finnish fall back to Finnish.

## Actor input object example

```json
{
  "businessIds": [
    "0112038-9",
    "0101120-3",
    "0211270-0"
  ],
  "companyForm": "",
  "maxResults": 100,
  "language": "en"
}
```

# Actor output Schema

## `companies` (type: `string`):

Company rows as a table.

## `runSummary` (type: `string`):

Status, counts, search totals, source attribution and request statistics.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "businessIds": [
        "0112038-9",
        "0101120-3",
        "0211270-0"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cliqtomedia/finland-ytj-company-register").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "businessIds": [
        "0112038-9",
        "0101120-3",
        "0211270-0",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cliqtomedia/finland-ytj-company-register").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "businessIds": [
    "0112038-9",
    "0101120-3",
    "0211270-0"
  ]
}' |
apify call cliqtomedia/finland-ytj-company-register --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cliqtomedia/finland-ytj-company-register"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/XQXC2aZ2yDEb02q7A/builds/HWvdv0UQ1TxDADqPF/openapi.json
