Czech Company Data — ARES Search, VAT & Directors avatar

Czech Company Data — ARES Search, VAT & Directors

Pricing

from $3.00 / 1,000 results

Go to Apify Store
Czech Company Data — ARES Search, VAT & Directors

Czech Company Data — ARES Search, VAT & Directors

Search Czech companies by name/IČO, or DISCOVER them by industry (NACE) + city + legal form, from the official ARES registry. Returns identity, VAT (DIČ), NACE, address, founding date, plus optional directors & share capital. Open data, no key.

Pricing

from $3.00 / 1,000 results

Rating

0.0

(0)

Developer

Berkan Kaplan

Berkan Kaplan

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

1

Monthly active users

17 days ago

Last modified

Share

Czech Company Data — ARES Registry 🇨🇿

foXLabs European company-registry series: UK · France · Estonia · Latvia · Poland · Slovakia · Slovenia · Denmark · Norway · Finland

🎉 Turn the Czech ARES registry into clean, structured company data — no login, no API key, one row per company, with the IČO, tax ID, legal form, NACE codes, address and, on request, the people in its statutory body and its registered capital. Built for KYB / compliance, B2B sales research and market-research teams.

🔍 What is Czech Company Data — and when should you use it?

Give this Actor IČO numbers, a company name, or a NACE code + city + legal form, and it returns the matching companies from ARES, the Czech Ministry of Finance's register of economic subjects, read through its public API. With one switch it adds each company's statutory body, supervisory board and registered capital from the public register.

Use it when you need: the registry record of known Czech companies by IČO; companies whose name contains a word; or the companies of a city by NACE branch, by legal form or by both — measured from 144 matches (a.s. companies in Olomouc that list a wholesale code) to 7,329 (every s.r.o. in Olomouc; 7,254 of them were delivered). "IT" on this page means: lists a code of NACE division 62.

Use something else when: you need e-mail addresses, phone numbers or websites — this Actor returns none — or a complete list of a very large search in one run: ARES holds 35,387 IT s.r.o. companies for Praha, and no run of that size was measured (see "The 1,000 limit").

🤖 Use with AI agents

Already on the Apify MCP server? Ask for this Actor by name: foxlabs/czech-company-data. Checked on 2026-10-08: the server lists it as the tool foxlabs--czech-company-data.

Your agent can pay for its own runs. For an agent with a wallet and no human to sign in, Apify sells a prepaid, spend-capped API token over x402 at agi.apify.com; such a token runs any Actor that uses limited permissions, as this one does (the terms of that path are Apify's own — see apify.com/agents.md). The Actor also meets Apify's conditions for per-request agentic payments — pay-per-event only, limited permissions, no Standby — and Apify Store lists it as eligible for them (read from the Store on 2026-10-08). The Actor charges the same events either way: one per company delivered, plus the run start.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

I want Czech company records from the Apify Actor `foxlabs/czech-company-data`.
Input, one of three ways: `icoList` is a list of IČO numbers (while it holds one, the other search fields are not used); `searchQuery` is one or more whole words of the company name (a part of a word finds nothing; several words must all be in the name); or discover companies with `naceActivity` (a CZ-NACE 2025 code that stands for its whole branch: "62" is all of division 62; a 2008 code such as "6201" finds nothing), `city` and `legalForm` ("112" = s.r.o., "121" = a.s., "100" = sole traders); `city` alone fails the run — it is not offered as a search; give a sector, a legal form or a name with it. `onlyActive` leaves out companies that have ended, are in liquidation or have an insolvency entry. `includeDirectors` adds the statutory body, the supervisory board and the registered capital. `maxResults` caps the rows (default 1,000); every row delivered is charged. The run's status message says how many companies were delivered and what was left out — read it and tell me.
Start with: {"icoList":["00177041","45274649"],"includeDirectors":true}
Ask me which companies or which sector and city I want, run the Actor, then show the companies as a table with name, IČO, tax ID, city and directors.

The Actor's machine-readable page is apify.com/foxlabs/czech-company-data.md: API examples, the MCP config, the input texts and a link to the OpenAPI definition (read on 2026-10-08).

📋 Overview

Why teams pick this Actor:

  • ✅ The official register, read live — every run queries the ARES API.
  • 🧭 Discovery, not only lookup — list the companies of a city that list a code of a NACE branch, without knowing a single name. A search over ARES's limit of 1,000 results is read in smaller searches: one run delivered 3,929 of the 3,931 IT s.r.o. companies ARES holds for Brno.
  • 👤 The people behind the company — with includeDirectors, 1,202 of 1,219 measured companies came back with at least one entry in the statutory body.
  • 💰 Pay only for companies delivered — a run that delivers nothing costs only the run start.
  • 🤖 Agent-ready — MCP tool + agentic payments.

✨ Features

  • 🔢 IČO lookup — exact company numbers, as many as maxResults allows.
  • 🔎 Name search — companies whose name has your word, as a whole word (several words: all of them); accents and case do not matter.
  • 🧭 Discovery — a CZ-NACE branch, a legal form and a city, combined.
  • 👥 Statutory body, supervisory board and capital — entries in force only.
  • 🚦 Status on every row — isActive, inLiquidation and insolvencyRecord; onlyActive filters on them.
  • 🧹 Clean schema — 21 camelCase fields, 28 with includeDirectors.

🎬 Quick Start

curl -X POST "https://api.apify.com/v2/acts/foxlabs~czech-company-data/runs?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"icoList":["00177041","45274649"],"includeDirectors":true}'

The call starts a run and returns it; the rows are in the run's default dataset. On 2026-10-08 this input returned Škoda Auto a.s. and ČEZ, a. s. with their boards and capital, in 4 seconds at 512 MB of memory; the run ended with the status message "Delivered 2 companies for 2 IČO numbers."

🚀 Getting Started (3 steps)

  1. Choose a way in — IČO numbers, a name, or a NACE code with a city and a legal form.
  2. Decide on directors — switch includeDirectors on if you want the people and the capital; it adds one lookup per company.
  3. Run and read the status message — it says how many companies were delivered and what was left out.

In the Console form icoList comes pre-filled with two examples; empty it to search another way.

📥 Input

{"icoList":["00177041","45274649"],"includeDirectors":true}

A run needs at least one of icoList, searchQuery, naceActivity or legalForm; without one it fails and says so. city alone fails the run too: it is not offered as a search, and the message says so and names what to add. The reason is not ARES — it answers such a search with the count, like any other over its limit (32,138 entities for Olomouc in October 2026) — but that a city can hold far more than a run reads: a test version of this Actor that read Olomouc alone in slices (one run from our own machine, not on the platform) delivered 11,189 of the 32,138, every one a natural person in business and not one company. Give legalForm, naceActivity or searchQuery with the city: s.r.o. + Olomouc returned 7,254 of 7,329.

"The previous test build" on this page is build 0.1.17, measured on the platform on 2026-10-09. This build was made from it. It differs in what a run does when it is started a second time, in the rules for a public register that does not answer, in two rules for capital written as free text and in how a few rare answers of ARES are read (see the changelog). Each of these was then run on the platform on 2026-10-09 (build 0.1.18): where a sentence below says "measured on this build", the number comes from those runs.

FieldTypeDescription
icoListarrayIČO numbers; one entry may hold several, separated by commas. While the list holds a number, the name and discovery fields are not used. Lost leading zeros are restored (177041 → 00177041) and a number given twice is looked up once. The status message names the numbers ARES does not know (record NOT_FOUND), separately those it did not answer for (NO_ANSWER), and the entries that cannot be an IČO. A list longer than maxResults is looked up only that far. Under a maximum charge the run looks up only as many numbers as the charge still covers, so every company it finds is delivered; the status message says how many numbers were not looked up and why, and the record NOT_DELIVERED lists them for a later run. Measured on the previous test build and again on this one: 120 numbers at a maximum charge of $0.06 ended after 19 lookups and 19 rows, with "101 more numbers were not looked up: the run's maximum charge covers no further company." and the 101 numbers in NOT_DELIVERED.
searchQuerystringA whole word of the company name; case and accents do not matter (skoda finds Škoda). A part of a word finds nothing: asked in Olomouc on 2026-10-08, servis returned 97 companies, serv and servi none, and autoservis 10 others (none of them among the 97). With several words every one must be in the name, in any order and not side by side: auto servis and servis auto returned the same single company, AUTO MOTO SERVIS ANDĚL s.r.o. (auto alone: 29). Of 1,935 names returned for servis, 4 do not contain it: sole traders listed under the person's name.
naceActivitystringA CZ-NACE 2025 code, digits only, standing for its whole branch: ARES matches a code only when a company lists exactly that code, so the Actor searches every code of ARES's list that starts with these digits — 62 (computer programming and consultancy) is 11 codes, 47 (retail) 82. 46 (wholesale), with 106, is read as two searches, and such a run's status message carries no total. A code outside the list (6201, from the 2008 classification) and a value with no digit (J) read nothing; the status message says why.
legalFormstringOne legal form by ARES code: 112 s.r.o., 121 a.s., 111 v.o.s., 113 k.s., 205 cooperative, 100 sole trader (searched as the codes 100–108), 421 branch of a foreign company, 141 public benefit company (o.p.s.), 301 state enterprise, 706 association. It also works with a city and no sector. Without it every legal form comes back, natural persons included.
citystringText ARES matches against the registered address: a municipality (Olomouc, Brno), or a district, city part or street to narrow a large search. Accents do not matter: Plzen and Plzeň each counted 345 a.s. companies, and the first 100 rows of the two answers were the same (the other 245 were not compared). Not exact — 45 of the 7,254 rows for s.r.o. + Olomouc have an address without the word.
addressQuerystringExtra filter on what ARES returned, also on IČO lookups: keep companies whose address contains this text; case and accents do not matter (plzen keeps Plzeň). The accents are new: the released build compared in lower case only. Measured on the previous test build: with Plzen, the 10 rows a run returned all spell Plzeň. Horní kept 3 of the 247 IT s.r.o. companies of Olomouc.
onlyActivebooleanLeave out a company that has ended (isActive is false), is in liquidation (inLiquidation) or has a live insolvency or bankruptcy entry (insolvencyRecord) — also on IČO lookups.
includeDirectorsbooleanAdd the statutory body, the supervisory board and the registered capital. Off by default in the API; ticked in the Console form. If the public register does not answer, see "directors is null" under Troubleshooting.
maxResultsintegerMost companies to deliver. Default 1,000; 1 to 100,000. In a search it is counted after onlyActive and addressQuery: the run reads on until that many are left. A list of IČO numbers is cut to its first maxResults numbers before any lookup, so with a filter fewer rows can come back. The rows of one search came in ascending IČO order in every measured run, so a low number returns the lowest IČO numbers, not a sample.

The 1,000 limit

ARES lists at most 1,000 companies per search; a larger search gets the count and no rows. The Actor then reads it in smaller searches, each company once: it cuts by legal form, then by tax office, then by NACE code (every division when you gave no sector) and last by city part — the parts met in the rows already read for the same tax office.

Measured on 2026-10-08 at 512 MB of memory:

SearchARES holdsDelivered
62 + Brno + s.r.o.3,9313,929, in 39 smaller searches (21 of them held rows) and 37 seconds
s.r.o. + Olomouc, no sector7,3297,254, in 444 smaller searches (315 held rows) and 216 seconds
62 + Brno, no legal form, maxResults 30007,705the first 3,000, from 17 smaller searches (5 held rows)
name servis, maxResults 15006,369the first 1,500, from 11 smaller searches (all held rows)
62 + Praha + s.r.o., maxResults 100035,387the first 1,000, from 21 smaller searches (all held rows)

"Smaller searches" is the number the status message gives: the searches ARES answered with a list, an empty list included; the answers that were over the limit again are not in it. The first search is {"naceActivity":"62","legalForm":"112","city":"Brno","maxResults":100000}; without maxResults a run stops at 1,000.

  • A few companies stay out of reach — 2 of 3,931 in the Brno run, 75 of 7,329 in the Olomouc run. The status message counts them: a company with no tax office on record, with no NACE code or with no city part in its address falls through the cuts.
  • A cap delivers the first slices, not a sample. With no legal form the cut starts with form 101: the first 3,000 of the 7,705 entities for 62 + Brno (3,931 of them s.r.o.) were all sole traders. Tax offices are asked in the order of ARES's list: a run for s.r.o. + Olomouc that its maximum charge stopped at 19 companies never reached Olomouc's own office, and 17 of the 19 have an address elsewhere.
  • A much larger search without a legal form is cut short by the budget below, and unevenly. The one measurement is the test of Olomouc alone described under Input (32,138 entities; that search is not offered): the budget of 40 over-limit answers ran out while the run was still cutting form 101, and 11,189 rows came back, not one of them a company. By the code, and in a simulated register, a sector or name search of that size is cut in the same order — form 101 first — and its status message names the legal forms it did not read; legalForm gives one form the whole budget. Between that size and the 7,329 of s.r.o. + Olomouc, read to 99 %, no run was measured.
  • The run stops cutting after 40 over-limit answers or 1,500 smaller searches asked (every one it asks counts, whatever the answer): ARES answers an over-limit search with an input error, and its operating conditions name repeated wrongly filled queries (see "How fast is it?"). The largest measured platform run (s.r.o. + Olomouc) used 27 of the 40 and 470 of the 1,500: of those 470, ARES answered 26 with "over the limit" again, 315 with rows and 129 with an empty list. All of Praha's 35,387 in one run was not measured — the capped run had spent 16 over-limit answers by its 1,000th row. Narrow such a search in city: asked on ARES directly that day, Praha Chodov held 574 IT s.r.o. companies; Praha 4 (6,079) was still over the limit.
  • What stopped the reading is in the run's OVER_LIMIT record (stopped), with the smaller searches that were asked and still held more than 1,000 (notListed) and those a budget stop or an outage left unasked (notAsked names the first 300 of them, slicesNotAsked counts them all). What a stop at maxResults or at the maximum charge left unread is not listed anywhere: a new run starts from the beginning.

📤 Output

One row per company, saved to the dataset.

{
"name": "Škoda Auto a.s.",
"ico": "00177041",
"vat": "CZ00177041",
"legalForm": "Joint-stock company (a.s.)",
"legalFormCode": "121",
"address": "tř. Václava Klementa 869, Mladá Boleslav II, 29301 Mladá Boleslav",
"city": "Mladá Boleslav",
"region": "Středočeský kraj",
"postalCode": "29301",
"nace": ["70200", "471", "77110"],
"primaryNace": "70200",
"foundingDate": "1990-11-20",
"endDate": null,
"isActive": true,
"inLiquidation": false,
"insolvencyRecord": false,
"activeRegisters": ["Ros", "Vr", "Res", "Rzp", "Nrpzs", "Dph", "Rs", "Red"],
"aresUrl": "https://ares.gov.cz/ekonomicke-subjekty?ico=00177041",
"source": "ARES — Administrative Register of Economic Entities (Czech Republic)",
"license": "Open data — Ministry of Finance of the Czech Republic",
"scrapedAt": "2026-10-08T20:27:16.696Z",
"directors": [{ "name": "ANDREAS DICK", "role": "Prokura", "type": "person", "from": null, "addressCountry": "CZ" }],
"directorsCount": 7,
"directorsTruncated": false,
"supervisoryBoard": [{ "name": "THOMAS SCHÄFER", "role": "předseda dozorčí rady", "type": "person", "from": "2026-07-01", "addressCountry": "DE" }],
"supervisoryBoardCount": 9,
"supervisoryBoardTruncated": false,
"capital": { "amount": 16708850000, "currency": "CZK" }
}

The example is a real row, with nace cut to three codes and each board to its first entry. "Filled" counts the 17,429 different entities the measured runs of 2026-10-08 delivered; the last four lines count the 1,219 companies read with includeDirectors: 219 IT s.r.o. in Olomouc (with onlyActive) and the first 1,000 a.s. in Brno — those 1,000 from a run of an earlier test build of this version, whose lists of people are built by the same code.

FieldWhat it isFilled
nameRegistered name17,429
ico / aresUrlThe company number (IČO) and the company's page on ares.gov.cz. Both are null for an entity ARES knows from the trade register only: 13 rows, all from name searches17,416
vatTax identification number (DIČ) — not proof of VAT payment: a VAT payer has Dph in activeRegisters (8,271 rows) or, as member of a VAT group, SkDph (89)10,017
legalForm / legalFormCodeLegal form in English for 29 ARES codes, otherwise the code itself (707)17,429
addressRegistered address as one line17,426
city / region / postalCodeMunicipality, region and postal code17,220
nace / primaryNaceEvery CZ-NACE code the company lists — 1 to 28 in the Olomouc IT run, two to five digits deep, with section letters such as G — and the first of them, which is not the main activity: Škoda Auto's list starts with 70200 and has 29100 (motor vehicles) in tenth place17,412
foundingDate / endDateDate of formation; date the entity ended, when ARES gives one — in none of these rows17,416 / 0
isActiveThe entity exists: active in the register of persons (or, with no entry there, in any source register) and no end date. A company in liquidation still existsfalse on 8
inLiquidationThe name carries "v likvidaci" or one of two rarer spellingstrue on 1,052
insolvencyRecordA live entry in the insolvency register or in the older register of bankrupts (Ir or Ceu in activeRegisters)true on 138
activeRegistersThe source registers that list the entity as active: Ros register of persons, Vr public register, Rzp trade-licence register, Dph VAT payers …17,429
source / license / scrapedAtTwo fixed labels — license is the Actor's own wording, not a licence text of ARES — and the time the record was read from ARES (UTC)17,429
directorsEntries in force in the statutory body, each with name, role, type (person or entity), from and addressCountry. An empty list: the public register has no entry in force, or no record. null: it did not answer for this company, asked twice, or answered with an error; the status message counts such rows (none in the measured runs)1,202 with at least one; 1,160 with someone other than a liquidator
directorsCount / directorsTruncatedNumber of different people; true when the list had more than 30 entries and was cut (never in these rows)1,219
supervisoryBoard (+ count, truncated)Entries in force in the other bodiess.r.o.: 1 of 219; a.s.: 483 of 1,000
capitalRegistered capital: amount and currency (CZK or EUR; any other currency word of the register would come through as written). Where the register holds the capital as free text, the amount is the number in front only when nothing but a currency follows it (110000,- Kč → 110000; 2 mil. Kč → null) and the number has no comma before exactly three digits (100,000 Kč → null: thousands to one writer, decimals to another); the currency is the one the text names as a word (Kč, CZK, korun českých; EUR, euro, €), and null when it names none or both. Six such texts were met, read again on the previous test build: 110000,- Kč → 110000 CZK; 2000000 → 2000000, no currency; 100 Kč → 100 CZK; sto tisíc korun českých and jedna koruna česká, written in words → no amount, CZK; and one whose text was not saved → 500000 CZK1,215; 9 of them (6 free texts, 3 amounts in euro) come from the first test build, which read them differently — see the changelog

About the people: the 1,219 companies carry 2,040 entries in directors — all with a role, 1,891 with a start date, 2,038 with an address country (CZ in 1,906). Roles come in Czech as registered, in 57 spellings (jednatel, Jednatel, Prokura); liquidators (68 entries) and holders of procuration (55) are listed too. addressCountry is the country of the registered address, not a citizenship: the public register's answer held no citizenship field on 2026-10-08, and ARES's API description lists one for the trade register only.

💼 Use cases

1. Companies of a city that list a NACE branch — names you do not know yet, with the people who run them. Input: {"naceActivity":"62","city":"Olomouc","legalForm":"112","onlyActive":true,"includeDirectors":true,"maxResults":300}. Output: 219 companies on 2026-10-08, each with at least one entry in its statutory body and a capital amount; onlyActive left out 28 more. Read it critically: all 219 list a code of division 62 — 188 the code 62, 31 only a longer one (62200, 6210, 62900) — but for 183 the first listed code belongs to another branch, and 2 have an address outside Olomouc. A company that lists no code of the division is not in the list, whatever it does.

2. Verify known companies — the registry record behind an IČO. Input: {"icoList":["00177041","45274649"],"includeDirectors":true}. Output: the two companies with tax ID, address, boards and capital. Use: KYB checks and CRM enrichment.

3. Find companies by a word in the name Input: {"searchQuery":"servis","city":"Brno","maxResults":100000}. Output: 436 companies on 2026-10-08, all ARES held for the search, every name containing the word. 29 are flagged — 24 inLiquidation, 6 insolvencyRecord, one of them both — the rows onlyActive leaves out; 2 have no IČO. Use: map a niche by how companies name themselves.

🔗 Integration

JavaScript / Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/czech-company-data').call({"icoList":["00177041","45274649"],"includeDirectors":true});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/czech-company-data').call(run_input={"icoList":["00177041","45274649"],"includeDirectors":True})
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item)

Written for apify-client 3 for Python, where call() returns a run object; with version 1 or 2 it returns a dict — write run['defaultDatasetId'] there.

Automation (n8n / Zapier / Make): send the IČO numbers from your CRM → read the JSON dataset → write tax ID, address and directors back.

📊 Pricing

Pay-per-event. Read from the Store on 2026-10-08: $0.003 per company written to the dataset ($3 per 1,000) plus Apify's run-start event, counted per GB of run memory: one event at 512 MB and at 1 GB, two at the default 2 GB (counted in the measured runs). Each delivered row is one event (in every measured run), also a row whose register lookup got no answer (directors: null). An IČO that ARES does not know writes no row and costs nothing. A run that delivers nothing costs only the run start: measured with a NACE code outside ARES's list and with a search whose 129 matches onlyActive all left out. With a maximum charge a search stops reading at the number of companies it covers: at $0.06 a search that holds 7,329 companies ended after 19, in 9 seconds, and said so. A list of IČO numbers is looked up only as far as the charge covers: 120 numbers at $0.06 ended after 19 lookups and 19 rows (measured on the previous test build and again on this one). A run that starts a second time — the platform moved it to another server, or you resurrected it — writes, and so charges, no row its dataset already holds (measured on this build: a search restarted at 400 rows ended with 1,200 rows, none twice, 1,200 charged; see the FAQ). View current pricing.

🚧 What it does not do

  • No e-mail, phone or website.
  • Not every company of a search over ARES's 1,000 limit — a few stay out of reach and a search of Praha's size was not run in full; see "The 1,000 limit".
  • No search by city alone — such a run fails with a message; a city needs a sector, a legal form or a name beside it (see Input).
  • No continuing in a new run. A search that ends at a cap, at the maximum charge, at its time limit or at an outage starts from the beginning in a new run and delivers — and charges — the same first rows again. Only a list of IČO numbers can be continued in a new run, from the run's NOT_DELIVERED record (written when the run finishes). The same run started again is another matter: see "What if the platform restarts my run, or I resurrect it?" in the FAQ.
  • onlyActive is a register test, not proof of trading. It leaves out what the registers and the name show — 1,174 of the 17,429 entities measured. A company with none of these marks stays in, whatever its business does.
  • No sector ranking. A NACE search finds every company that lists a code of the branch, whatever its main business (see use case 1).
  • People are names, roles, start dates and the country of the address — no date of birth, street address or citizenship. An entry of type entity can be an individual: 24 of the 77 measured are liquidators entered under a business name.
  • No financial statements and no shareholders.

❓ FAQ

Do I need an account, login or API key for ARES? No. The Actor reads the public ARES API.

How current is the data? Every run queries ARES live.

How fast is it? Measured at 512 MB of memory: two companies by IČO with directors took 4 seconds; 436 companies by name 5 seconds; "The 1,000 limit" times two large searches. includeDirectors adds one request per company: 219 companies took 35 seconds (the released build: 216 in 18 — requests are now spaced). These runs were made on test builds that wrote every row at the end. This build writes rows while it reads — every 200 companies, or after a minute when fewer are waiting — and sets the status message Delivered … so far; still reading. after each write. A run that is aborted or cut off by its time limit ends without a closing message: it keeps the rows it has written (they are charged) and that last progress line. Measured on the previous test build, which wrote the same way: the searches above took the same time to within 6 seconds, the log shows a progress line after every 200 rows, and a run with a time limit of 90 seconds ended TIMED-OUT with 400 rows, 400 of them charged, no closing message and the status "Delivered 400 companies so far; still reading." Not measured on the platform: the write after a minute (no measured search kept fewer than 200 rows for that long; in a simulated register a narrow search wrote its first 99 rows after 60 seconds) and an abort. A list of IČO numbers is paced like every other request: 1,000 numbers are about 2.4 minutes of lookups, 4.8 with includeDirectors — computed from the pace; the longest list measured was 19 lookups. The Actor spaces its requests 143 ms apart — about seven a second, 420 a minute: in ARES's operating conditions, which its API is offered under (read on 2026-10-08), the Ministry of Finance reserves the right to restrict or block access to the ARES web application for users who send more than 500 queries a minute or repeatedly send wrongly filled queries.

Are former directors included? No. The Actor keeps the entries the register has not struck out and, per person and role, the newest one.

What does each row represent? One economic subject in ARES, once per run — also when the run is started a second time (next question). It can be a natural person: a sole trader's row holds the person's name and registered address.

What if the platform restarts my run, or I resurrect it? Apify can move a running Actor to another server; the run then starts again from the top, with the same input, the same dataset and what was already charged. Resurrecting a run — for example with a longer time limit or a higher maximum charge — does the same. This build first reads which rows its dataset already holds (by IČO; by name and address for the few entities without one). It then reads ARES from the beginning again — for a list of IČO numbers, only the numbers that have no row yet — and writes just the rows that are missing, so no row is written or charged twice. The rows that were there count as delivered: maxResults, the maximum charge, the closing message, OUTPUT and NOT_DELIVERED are those of the whole run, and a record an earlier start left behind is replaced or removed. The log says "This run was started again by the platform: its dataset already holds … rows; continuing." Three limits. When the dataset already holds everything the run may deliver, the new start reads nothing: its closing message is shorter than one uninterrupted run's, and for a list of IČO numbers NOT_DELIVERED then holds every number without a row — also the numbers ARES does not know or a filter would leave out. When ARES or the public register does not answer the new start, the run ends with a message that counts the rows already there instead of failing; a start that still fails — a sector search whose code list ARES does not return, for one — adds how many rows the dataset holds, and a start that cannot read its dataset fails before it asks ARES anything. And the Actor relies on the dataset listing every row that was written before the restart. Measured on the platform on this build (2026-10-09): a sector search of 1,200 companies with directors, restarted at 400 rows, ended with 1,200 rows, none twice, 1,200 charged, and the log line above; the same search under a maximum charge covering 619 rows, restarted at 400, ended with 619, none twice; three finished runs resurrected (19, 10 and 219 rows) kept their rows and charged none again — Apify counts its run-start event once more for a resurrected run. Before that, 36 runs against a simulated register and five with the real Apify SDK and a local dataset ended the same way.

Can I export to CSV / Excel / JSON? The rows are JSON in the Apify dataset. CSV and Excel are Apify's dataset exports and were not tested for this Actor; nace, directors and supervisoryBoard are lists.

🐛 Troubleshooting

  • The run succeeded but the dataset is empty — the status message says why: no company matched (check how the city and the name are written), a filter removed every match ("129 matched in ARES and were left out by onlyActive."), or the sector cannot be searched ("No company read: "6201" is not a code of CZ-NACE 2025, the classification ARES searches." — it goes on to name the codes of the division).
  • Fewer companies than ARES holds — the status message names the reason: a filter, the cap ("(stopped at maxResults 200)"), the charge limit ("The run stopped at its maximum charge; a new run starts from the beginning again.") or companies no smaller search could reach. Read from the code, in no measured run: a smaller search ARES does not answer in three tries is left out and the message says so; after five in a row the run stops asking; an error answer part-way through a search is reported as that, with ARES's own words. How long giving up takes depends on how ARES fails (computed from the Actor's waits): a request that is refused or answered with a server error has had its three tries within about 8 seconds, so five in a row are over in under a minute; a request that hangs is given 60 seconds a try, so a search stops asking after about 15 minutes of hanging requests, and a list of IČO numbers — which first finishes the lookups it has started, up to 50, five at a time — after up to 30.
  • directors is null, or the run stopped at the public register — a company the public register does not answer for (or answers with an error) is asked once more after the others. If it still has no answer, the run asks the register for a company known to have a record: the last company of the run it returned a record for or, before the first one, Škoda Auto (00177041) and then ČEZ (45274649). A record comes back: the register is alive, and the company's row is delivered with directors, supervisoryBoard and capital set to null, charged like any row and counted in the status message. No record comes back: the register is down — the run writes the rows of that batch that have their answer, holds the others back, asks and writes nothing further and ends with "The public register stopped answering, so the run stopped there: …", whether the batch is one company or 200. A "no record" answer is an answer for the entity it was asked about — empty lists — but it never counts as proof that the register is alive. (Measured on 2026-10-09: for three sole traders without a record the register answered HTTP 404 with the code NENALEZENO, and a run of 40 sole traders with includeDirectors read 40 such answers.) A second stop limits the rows without what you asked for: once 25 companies of a run have been left with null and they are more than half of the companies asked so far, the run ends the same way ("The public register answered for fewer than half of the … companies the run asked it about"); a register that answers for half of them or more is not stopped. If the register has returned no record for any company of the run when it stops, no row of that batch is written — none without an IČO either — and a run whose dataset is still empty fails. Run again later, or without includeDirectors. Measured on this build: 40 sole traders asked with includeDirectors came as 40 rows with empty boards and no null, and the run did not stop. A register that does not answer was met in no measured run: that path was run against a simulated register only. Not recognised: a register that answers "no record" for companies that have one — their rows would come with empty lists. When register requests hang instead of failing, giving up takes about 12 minutes for a run of up to five companies, about 18 for a larger one, and up to about 15 when the register stops in the middle of a run (computed from the waits: three tries of 60 seconds for each request, five requests at a time).
  • An IČO is missing from the result — the status message names it. The entries 00177041, 45274649, 177041, 99999999, abc and 1234567890123 ended with "Delivered 2 companies for 3 IČO numbers. Not in ARES: 99999999." and "Not an IČO (one to eight digits): abc, 1234567890123."
  • My name search returned Škoda Auto and ČEZ — the pre-filled icoList was still there; the status message says "searchQuery was not used: with IČO numbers in icoList the run is a lookup of those numbers. Empty icoList to search."
  • The run failed — the input had none of icoList, searchQuery, naceActivity and legalForm (city alone is not offered as a search; the message names what to add); no entry of icoList was an IČO; ARES gave no answer in three tries — to the search itself, to every IČO lookup, or for the CZ-NACE code list a sector search needs; or, with includeDirectors, the public register returned a record for none of the companies it was asked about. No row is written; start the run again. Measured on the previous test build, and {"city":"Olomouc"} again on this one: both failed with their messages and were charged the start event only. The other failures are read from the code and were run against a simulated register only; there, a search address that answers HTTP 404 counts as "no answer", not as "No company matched". A request that hangs is given 60 seconds a try: a search whose first request hangs fails after about 3 minutes.

The Actor reads a public register published by the Czech Ministry of Finance. The rows contain personal data: the names of company officers and the country of their address and, for sole traders, the person's name (with an academic title such as Ing., Mgr. or Bc. in 1,438 of 3,206 measured rows), registered address and tax ID. A sole trader's tax ID is not CZ + IČO as a company's is: the 902 measured values are CZ followed by 9 or 10 digits, the first six reading as a date in 875. Personal data is protected by the GDPR and similar laws, so only process it with a legitimate basis. The license column is the Actor's own label — read ARES's conditions yourself before you republish the data. foXLabs is not affiliated with the Czech Ministry of Finance.

🤝 Support & contact

Changelog

0.1.18 — 2026-10-09 — a NACE code covers its whole branch, searches over ARES's 1,000 limit are read in slices, onlyActive works; README rewritten

  • A NACE code now stands for its whole branch. ARES matches a code only when a company lists exactly that code, so 62 missed every company that lists 62200 and not 62. The Actor now searches every CZ-NACE 2025 code that starts with the one you give (62 → 11 codes, 47 → 82). Measured on 2026-10-08 for s.r.o. in Olomouc: code 62 alone 216 companies, the whole division 247. A code of the older 2008 classification (6201) still reads no company, but the status message now says so and names the codes of its division.
  • A search that holds more than 1,000 companies no longer comes back empty. ARES lists at most 1,000 per search and answers a larger one with the count and no rows. The Actor now reads such a search in smaller ones — by legal form, then tax office, then NACE code, then city part — and its status message says how many of ARES's total it delivered and how many it could not list. The legal-form split uses ARES's complete list of forms; it used 17 hand-picked ones and lost the others without a word. A request ARES does not answer costs one of the smaller searches, not the run: what the others returned is delivered and the message says what is missing; after five unanswered requests in a row the run stops asking.
  • onlyActive now removes something. It keeps a company that exists, is not in liquidation and has no live entry in the insolvency register or in the older register of bankrupts. The earlier test was true on every row measured from the earlier build (1,008 of 1,008) and removed nothing. New fields inLiquidation, insolvencyRecord and endDate; isActive now means "exists": active in the register of persons and no end date.
  • citizenship is gone, addressCountry is new. The public register does not publish citizenship — the field the Actor read is absent from its answers on 2026-10-08, and ARES's API description lists it for the trade register only — so citizenship was empty in every row: all 1,047 entries (1,033 persons and 14 entities) in the measured runs of the earlier build. Each person in directors and supervisoryBoard now carries addressCountry, the country code of the registered address.
  • Unknown is null, not "none". When the public register does not answer for a company, directors, supervisoryBoard and their counts are null (they were empty lists, the same as a company with no board) and the status message counts those rows. Such a company is asked once more after the others first, so a blip of a few seconds leaves no gap. If it still has no answer, the run asks the register for a company known to have a record — the last one it returned a record for, or Škoda Auto and ČEZ. A record comes back: the register is alive and the row is delivered with null. None comes back: the register is down, and the run writes the rows that have their answer, nothing after them, and says so — whatever the number of companies waiting. It stops the same way once 25 companies have been left with null and they are more than half of those asked. When the register has returned no record at all and the dataset is empty, the run fails — before, every row came without directors and was charged. A "no record" answer never counts as proof that the register is alive, and an error the register answers for a company is no answer (null), not an empty board. (Measured on this build: 40 sole traders asked with includeDirectors came as 40 rows with empty boards, no null, and the run did not stop — the register answered "no record" for each. A register that is down was met in no measured run: that path was run against a simulated register only.) IČO numbers ARES does not know are named there too, and so is an entry that cannot be an IČO. Leading zeros lost in a spreadsheet are restored (177041 → 00177041), one entry may hold several numbers, and a list longer than maxResults is cut with a word about it. When ARES answers none of the lookups the run fails instead of ending as an empty result.
  • Share capital with a decimal comma is read. 42700000,00 used to become null (2 of the 1,217 companies with a capital entry in the measured runs). Capital the register holds as free text (6 of those companies) is read as the number in front when nothing but a currency follows it, with the currency the text names as a word — otherwise null: read again on the previous test build and on this one, 110000,- Kč gave 110000 CZK, 2000000 gave 2000000 with the currency null, 100 Kč gave 100 CZK, one whose text was not saved gave 500000 CZK, and the two written in words (sto tisíc korun českých, jedna koruna česká) gave no amount and CZK. A text such as 2 mil. Kč gives no amount rather than 2. Two rules are newer than those runs and were run on the reading code alone: a number with a comma before exactly three digits is not read (100,000 Kč could be a hundred thousand or a hundred), and a text that names both currencies gets none. None of the five texts that are known is of either kind. The register's currency word EURA is delivered as EUR (3 companies: 120000, 100000 and 80000 EUR on the previous test build and on this one).
  • Legal-form labels corrected. Code 141 is a public benefit company (it was labelled "Institution"), 145 a unit owners' association (it was "Branch"), 751 an interest association of legal entities (it was "Association"). Twelve codes that delivered the bare code now carry a label (102–108 sole traders and farmers, 117, 118, 161, 501, 736). "Sole trader" in the input now covers codes 100–108; it sent code 100, which holds almost nobody.
  • The form described two searches wrongly. It said ARES refuses a search by city alone. ARES does not: it answers with the count, like any search over its limit (32,138 entities for Olomouc in October 2026). The Actor still does not offer that search, for another reason — a city can hold far more than a run reads: a test version that read Olomouc alone in slices (one run from our own machine, not on the platform) delivered 11,189 of the 32,138, all of them natural persons in business and not one company. Such an input fails as before, now with a message that gives this reason and asks for a sector, a legal form or a name beside the city. The form also said a name search finds names that "contain" the text; ARES matches whole words (servis 97 companies in Olomouc, serv none) and, with several words, every one of them; the form now says so.
  • Input that cannot be searched says so. A sector with no digit (J) used to be dropped, and the run delivered the companies of the other filters alone; it now reads nothing and says why. A name, sector, form or city typed next to IČO numbers is not used, and the status message says so. A sector search needs ARES's CZ-NACE code list: when ARES does not return it the run fails instead of searching the one code as typed.
  • Requests are spaced 143 ms apart — about seven a second, and a rate-limit answer makes the whole run wait. In ARES's operating conditions the Ministry of Finance reserves the right to restrict access for users who send more than 500 queries a minute; a run with includeDirectors sent its register lookups as fast as they returned. Such a run now takes about twice as long: the same Olomouc search returned 216 companies in 18 seconds before and 219 in 35 now. A list of IČO numbers is paced the same way — it was looked up five numbers at a time with no pause — so 1,000 numbers are now about 2.4 minutes of lookups (computed from the pace; the longest list measured was 19 lookups). Rows are written while the run is still reading — every 200 companies, or after a minute when fewer are waiting — so a run that is aborted or reaches its time limit keeps what it has written and its last progress line (Delivered … so far; still reading.); every row used to be written at the very end, and such a run delivered nothing. It still ends without a closing message. A run with a maximum charge stops reading at the number of companies that charge covers; it used to read the whole search, and every company's public-register record, before writing a fraction. A list of IČO numbers is looked up only as far as the charge covers, and the numbers left are in the run's NOT_DELIVERED record. (Measured on the previous test build: a progress line after every 200 rows; a run cut off by a time limit of 90 seconds kept its 400 rows — charged — and its progress line; 120 numbers at a maximum charge of $0.06 ended after 19 lookups, with 101 numbers in NOT_DELIVERED. The write after a minute and an abort were run against a simulated register only.)
  • A run that is started again writes and charges no row twice. Apify can move a running Actor to another server, and a run can be resurrected: it then starts from the top with the same input, dataset and charges. Now that rows are written while the run reads, such a start would write the rows of the earlier one a second time and charge them again. So every start first reads which rows its dataset already holds (by IČO; by name and address for the few entities without one), reads ARES again — a list of IČO numbers only for the numbers without a row — and writes just what is missing. The rows already there count as delivered: maxResults, the maximum charge, the closing message, OUTPUT and NOT_DELIVERED are those of the whole run, and the log says that the run was started again and with how many rows. When the dataset already holds everything the run may deliver, the new start reads nothing and its message is shorter (for a list, NOT_DELIVERED then holds every number without a row). (Measured on the platform on this build, 2026-10-09: a sector search of 1,200 companies with directors, restarted at 400 rows, ended with 1,200 rows, none twice, 1,200 charged; the same search under a maximum charge covering 619 rows, restarted at 400, ended with 619, none twice; three finished runs resurrected kept their 19, 10 and 219 rows and charged no row again. Before that, 36 runs against a simulated register and five with the real Apify SDK and a local dataset ended the same way.)
  • Smaller corrections. addressQuery ignores accents as well as case. An error ARES answers part-way through a search is reported as an error, in ARES's words (the released build set no status message at all). When a budget ends a search that had no legal form, the status message names the legal forms it did not read. The run's OUTPUT record says why the run stopped (stopped — also maxResults for a list that was cut at it) and how many companies it read and did not write (notWritten); OVER_LIMIT names the smaller searches left unasked (notAsked, the first 300; slicesNotAsked counts them all) and those answered with an error (errors). An HTTP 404 from ARES's search address is a request without an answer — tried three times, then the run fails — where the run used to end as an empty result. An IČO lookup ARES answers with an error other than "not found" or "wrong input" is reported as unanswered (NO_ANSWER), not as a number ARES does not know. (The last two were run against a simulated register only; no measured run met such an answer.)
  • The README's examples did not match this Actor. They used input keys it does not have (queries, maxResultsPerQuery, with a literal undefined value) and the input table listed phantom fields (maxConcurrency, includeRaw). Every example now uses the real input and was run on the platform during the measurements of 2026-10-08, on test builds of this version; the output table says how often each field was filled in measured runs.
  • The Python example works with the current Apify client. It read the results with run['defaultDatasetId']; with apify-client 3 for Python call() returns a run object and that line raised TypeError: 'Run' object is not subscriptable after the run had finished. It now reads run.default_dataset_id; with client version 1 or 2, keep run['defaultDatasetId'].
  • No pricing change. Output changes: citizenship removed; addressCountry, inLiquidation, insolvencyRecord, endDate added; directors and supervisoryBoard can be null; legalForm has a label for twelve more codes and a corrected one for 141, 145 and 751; scrapedAt is the moment the entity's record was read from ARES (it was the moment the row was built); capital.currency is EUR where it was EURA, and CZK, EUR or null where it was TEXT; capital.amount is read from free text and from amounts with a decimal comma, where it was null. Behaviour changes for inputs that already exist: a NACE search returns more companies (the whole branch); a search over the limit returns rows; onlyActive removes companies; isActive is false for an entity the register of persons no longer lists as active, or that has an end date; in a search maxResults counts the companies left after onlyActive and addressQuery (the search was cut before the filters); a list of IČO numbers longer than maxResults is cut to its first maxResults numbers before the lookups, and the numbers beyond are named (the whole list was looked up, filtered and then cut, without a word); an IČO given twice is returned once; a NACE code outside the classification, or with no digit, reads nothing; addressQuery also keeps addresses that differ from the text only in accents; a run that is aborted or reaches its time limit keeps the rows it had written, and they are charged — it used to deliver none; with includeDirectors, a run stops when the public register stops answering and fails when it returns no record for any company — it used to deliver every row without directors; a run with includeDirectors takes about twice as long, and a list of IČO numbers takes longer too (its requests are spaced now).

0.1 — 2026-09-07

  • The README was regenerated from a template shared by many Actors; the entry of that day read "Enabled AI-agent payments (x402) + rebuilt the README to the full standard". The label is the generator's: the builds of that day were numbered like the others of this Actor. That README is the one the entry above corrects — its examples and parts of its text did not describe this Actor.

0.1.2 — 2026-07-28

  • directors[] / supervisoryBoard[] return the entries in force. The earlier filter relied on end dates that ARES leaves blank on most historical rows, so departed officers were listed as current. The Actor now drops every entry the register has struck out.
  • Appointments without a start date are no longer discarded; they appear with from: null.
  • New directorsCount / supervisoryBoardCount (different people, not rows) and directorsTruncated / supervisoryBoardTruncated (the 30-entry cap reports when it bites).

0.1.1 — 2026-07-28

  • "Include directors & capital" is ticked in the Console form, so the pre-filled run on Škoda Auto and ČEZ returns the statutory body, the supervisory board and the registered capital. The API default is unchanged (false).

0.0

  • Initial release, 2026-07-09 (the Actor's first changelog called it 0.1): Czech companies from the ARES registry — IČO, tax ID (DIČ), legal form, NACE codes, registered address and founding date, with opt-in statutory body, supervisory board and registered capital.