PRH Finland Company Lookup — Official YTJ Business Registry API
Pricing
from $2.40 / 1,000 successful lookups
PRH Finland Company Lookup — Official YTJ Business Registry API
Look up Finnish companies by business ID (Y-tunnus) against the Finnish Patent and Registration Office's official, free YTJ registry. Get company name, legal form, main business line (TOL code), status, and registered address. Pay only for IDs that resolve to a real company.
Pricing
from $2.40 / 1,000 successful lookups
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 hours ago
Last modified
Categories
Share
PRH Finland Company Lookup
You give it a list of Finnish business IDs (Y-tunnus). It queries Finland's official company register — maintained by the Patentti- ja rekisterihallitus (PRH, the Finnish Patent and Registration Office) — and hands back one row per ID: the company's registered name, legal form, main business line, current status, and registered address. No scraping, no API key, no login — it calls PRH's own open-data YTJ API directly, the same source you'd query by hand on the YTJ website.
Feed it a handful of IDs to check a few counterparties, or a few thousand to enrich a whole outbound list of Finnish companies. Either way you get back one dataset row per ID, and you only pay for the ones that actually resolve to a registered company.
Who it's for
The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and per-domain: a few tenths of a cent for a row that was actually found, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists — VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No seat licence, no monthly minimum, no credit system to decode.
Here, the identifier is a Finnish business ID and the official source is PRH's YTJ registry — the same register banks, auditors, and Finnish counterparties check before signing anything.
Why this one
- Reads the trade register, not a cached status flag. PRH's raw
company.statusfield is a constant "2" for every company in the register, active or dissolved — this actor ignores it and derivescompanyStatusfrom the trade register's own register/deregister entries plus bankruptcy, restructuring, and liquidation codes, so a status ofRegistered (Bankruptcy proceedings)means what it says. - One request per business ID, synchronously. No polling, no async job to check back on — you send the batch and read the dataset when the run finishes.
- Business-ID format is validated before a request is sent. An input that isn't
NNNNNNN-Ncomes backBAD_FORMATimmediately, without spending a request against PRH. - Every entity type PRH registers, not just limited companies. Public and private limited
companies, cooperatives, and other registered legal forms are all covered —
companyFormCodeandcompanyFormDescriptiontell you which. - A miss still gets you a row. A business ID that doesn't resolve comes back
found: false,status: "NOT_FOUND", and is never charged. - Address comes back as a real object, not one merged string. Street, postal code, city, and
country are separate fields inside
address, so you're not left parsing a free-text address block before you can do anything with it.
What you get
One flat row per business ID:
| Field | Type / format | Description |
|---|---|---|
query | string | The business ID as you submitted it |
found | boolean | true if PRH returned a matching company |
status | string | OK, NOT_FOUND, or BAD_FORMAT |
businessId | string, NNNNNNN-N | The business ID as registered with PRH |
name | string | Registered company name |
registrationDate | date, YYYY-MM-DD | Date the business ID itself was registered |
companyFormCode | string | PRH's numeric code for the legal form (e.g. 16) |
companyFormDescription | string (Finnish) | The legal form in plain language (e.g. Julkinen osakeyhtiö) |
mainBusinessLineCode | string | TOL 2008 business-line code (e.g. 2610) |
mainBusinessLineDescription | string (Finnish) | The business line in plain language |
companyStatus | string (Finnish) | Derived from the trade register's own entries, e.g. Registered, Ceased, or Registered (Bankruptcy proceedings) |
registeredOffice | string | Registered municipality (kotipaikka), in Finnish |
address | object | { street, postCode, city, country } — registered street address |
scrapedAt | ISO timestamp | When this row was fetched |
companyFormDescription, mainBusinessLineDescription, and companyStatus come back in Finnish —
that's the language PRH's own registry uses. address is a nested object, not four flat columns;
if your destination table needs it flat, split it downstream or select just address and unpack it
there.
Price
$4 per 1,000 business IDs, plus a $0.005 start fee. Misses (found:false) are never charged.
That's $0.004 per business ID that actually resolves to a company, dropping to $0.0024 on paid Apify tiers. 1,000 business IDs through this actor: ~$4 if every one is found, less if some aren't. The same 1,000 rows through a credit-based enrichment platform: $80–$400. There's no seat licence and no monthly minimum — you pay for rows, not for access.
How to use
- In the Apify Console. Open the actor page and click Start — the
businessIdsfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~prh-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"businessIds":["0112038-9","0201256-6"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
- Paste your Finnish business IDs into
businessIds, one per entry, inNNNNNNN-Nformat (e.g.0112038-9). - Turn on
testRunfirst if you want to sanity-check the shape of your list against just the first 5 IDs before spending on the full batch. - Run the actor. Each ID becomes one dataset row —
found: truerows carry the company record,found: falserows tell you why (NOT_FOUNDorBAD_FORMAT) and cost nothing. - Use
columnsto trim the output to only the fields you need,onlyFoundto drop misses from the dataset entirely, andincludeKeywords/excludeKeywordsto filter rows by content (for example, keeping only rows wherecompanyStatuscontains "Registered"). - Pull the results into your table however you already work with Apify datasets — the API directly (see below), the Apify Console's dataset export (CSV, JSON, Excel), or an MCP-connected agent that runs the actor and reads the dataset back for you.
There's no separate "search by name" step: PRH's API is keyed on the business ID, so this actor is built for lists where you already know the ID (from an invoice, a contract, a CRM field, or a prior enrichment step) and need the registry record that goes with it.
Input
{"businessIds": ["0112038-9","0201256-6"]}
One business ID per line, in NNNNNNN-N format. Accepted formats: 0112038-9.
{"businessIds": ["0112038-9", "0201256-6"],"testRun": false,"onlyFound": false,"maxConcurrency": 5}
businessIds is a list of Finnish business IDs (Y-tunnus), in NNNNNNN-N format,
e.g. 0112038-9. One dataset row is returned per business ID; rows with
"found": false are never charged. Turn on testRun to try your list against just
the first 5 IDs before running the full batch. Optional includeKeywords /
excludeKeywords filter rows by content, maxResults caps the run early, and
columns lets you pick which fields to return.
Sample output
| query | found | status | businessId | name | registrationDate | companyFormCode | companyFormDescription | mainBusinessLineCode | mainBusinessLineDescription | companyStatus | registeredOffice | address | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0112038-9 | true | OK | 0112038-9 | Nokia Oyj | 1978-03-15 | 17 | Public limited company | 70100 | Activities of head offices | Registered | {"street":"Karakaari","postCode":"02610","city":"ESPOO","country":null} | 2026-08-23T21:02:34.491Z |
One row per business ID, for example:
{"query": "0112038-9","found": true,"status": "OK","businessId": "0112038-9","name": "Nokia Oyj","registrationDate": "1902-05-24","companyFormCode": "16","companyFormDescription": "Julkinen osakeyhtiö","mainBusinessLineCode": "2610","mainBusinessLineDescription": "Elektronisten komponenttien valmistus","companyStatus": "REGISTERED","registeredOffice": "Espoo","address": {"street": "Karakaari 7","postCode": "02610","city": "Espoo","country": "FI"},"scrapedAt": "2026-08-21T10:00:00.000Z"}
A business ID that isn't registered with PRH still gets a row ("found": false,
"status": "NOT_FOUND" or "BAD_FORMAT"), so you always get one row per input, but
you're never charged for that.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~prh-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"businessIds":["0112038-9","0201256-6"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~prh-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"businessIds":["0112038-9","0201256-6"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~prh-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"businessIds":["{{business ID}}"]}, mapping the row's business ID into the businessIds array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Finland Company Registry Lookup — PRH YTJ API" — the agent will find and run this actor.
Tips
- Run with
testRunon first if you're not sure your list is formatted correctly — it costs nothing to check 5 IDs againstBAD_FORMATbefore committing the full batch. - Filter on
companyStatusrather than assuming every returned row is an active company — a dissolved or bankrupt entity is stillfound: true, it's just not a going concern anymore. - If you only need name and status for a KYB check, set
columnsto just those two fields — you're billed the same either way, but a narrower table is easier to work with downstream. mainBusinessLineCodeis a TOL 2008 code, Finland's national adaptation of NACE — useful for matching against industry filters that already speak NACE/TOL.- Business IDs are case- and whitespace-insensitive on the way in, but the format check is strict: it has to be seven digits, a hyphen, one check digit.
- Keep the raw
companyStatusstring rather than reducing it to a boolean "active" flag downstream — it can carry a bankruptcy, restructuring, or liquidation qualifier alongside the register state, and collapsing that to true/false throws away exactly the detail a KYB check needs. - If you're enriching a list sourced from invoices or contracts, expect some IDs to be typos or
outdated —
BAD_FORMATandNOT_FOUNDrows are free, so there's no cost to running the whole list through and cleaning it based on what comes back.
vs. alternatives
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (prh-company-lookup) | $0.004 per business ID that resolves (less on paid tiers), $0.005 actor start, nothing for a miss | Registered name, legal form, main business line, trade-register-derived status, and address for any Finnish business ID, in a flat row your table can read directly | Finland only, and descriptions come back in Finnish. It doesn't cover filings, ownership, or financials — just the registry record. |
| PRH's YTJ portal directly | Free | The same data, from the same source | It's the same source — this actor exists for the batch: hundreds of business IDs in, one row out per ID, retries and format-checking handled, in the format your table already reads. One business ID, once? Use the portal. |
| Clay | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step. |
| Doing it yourself | Your time, plus keeping up with PRH's field structure (the API's raw company.status is a constant across all companies — you'd have to discover and handle that yourself) | The same data | The parsing, the format validation, and the trade-register-vs-status distinction, all absorbed into one call. |
Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
What happens if a business ID isn't registered with PRH?
You get a dataset row with "found": false and "status": "NOT_FOUND" — PRH's registry has no
company under that ID — and the row is never charged.
What format does a business ID need to be in?
NNNNNNN-N — seven digits, a hyphen, then one check digit, e.g. 0112038-9. Anything else is
rejected up front as BAD_FORMAT, before a request is even made to PRH, and it's never charged
either.
Are there rate limits?
maxConcurrency controls how many requests run in parallel against PRH's API (default 5). PRH's
open-data API doesn't publish a documented hard limit, but running very high concurrency against
any public government API risks throttling — the default is a reasonable starting point for large
batches.
How fresh is the data?
Each row reflects what PRH's registry returns at the moment the actor calls it — this is a live
lookup, not a cached snapshot. scrapedAt on each row is the fetch timestamp.
Do I need proxies or a PRH account? No. PRH's YTJ API is free, public open data — no credentials, no proxy configuration. This actor calls it directly.
Is this personal data, and does GDPR apply? No — a Finnish business ID and its registered company record are public registry data about a legal entity, not personal data about an individual. This actor doesn't look up or return information about company officers, shareholders, or any named individual.
Can I schedule this to run automatically? Yes, through Apify's built-in task scheduler — set up a Store Task against a saved list of business IDs and run it on a cron schedule from the Apify Console.
Can an AI agent call this directly? Yes — it's registered with the Apify MCP server, so an MCP-connected agent (Claude, Cursor, or similar) can find and run it by name, no separate integration code needed.
Does this cover businesses outside Finland?
No — only entities registered with a Finnish business ID (Y-tunnus) in PRH's YTJ registry. For a
Norwegian counterpart use brreg-company-lookup; for a lookup across multiple national registries
in one call, use company-registry-unified-lookup.
Can I look up a company by name instead of business ID? No — PRH's own API is keyed on the business ID, not name search, so this actor is too. If you're starting from a company name, you'll need to resolve it to a business ID first (PRH's YTJ website supports name search directly).
Why does companyStatus sometimes show two things at once, like "Registered (Bankruptcy
proceedings)"?
Because a company can be both formally registered and in an insolvency process at the same time —
Finnish company law doesn't deregister a business the moment it enters bankruptcy or restructuring.
This actor reports both facts together rather than collapsing them into one misleading word, and it
reads the trade register's own entries to do it, not PRH's raw status code (which stays "2" for
every company regardless of health).