# European Company Financials - ESEF XBRL Annual Reports (`publicdata/esef-european-company-financials`) Actor

Export audited financial statements of European listed companies from ESEF and UKSEF filings: revenue, profit, assets, equity and cash flow, with the prior year alongside. Filter by country, period or LEI. Figures come from IFRS-tagged XBRL, not from parsing PDFs.

- **URL**: https://apify.com/publicdata/esef-european-company-financials.md
- **Developed by:** [PublicData](https://apify.com/publicdata) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $17.00 / 1,000 financial statements

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

**Audited financial statements of European listed companies as a spreadsheet: revenue, profit, assets, equity and cash flow, with the prior year in the next column. Read from IFRS-tagged XBRL, not from parsing PDFs.**

Every listed company in the EU has been required to file its annual report in Inline XBRL since 2021. The numbers are therefore already machine-readable and already standardised — the problem has only ever been getting at them. This Actor does that, over the repository XBRL International maintains at `filings.xbrl.org`.

Every XBRL Actor on Apify today reads the US SEC. **This one reads Europe.**

### What you get

One row per filed statement, with **69 columns**:

- **Identity** — LEI, company name, country, reporting period, currency, filing regime (ESEF, UKSEF, UAIFRS). The LEI joins straight onto GLEIF and onto anything else keyed by LEI.
- **Income statement** — revenue, operating profit, profit before tax, income tax, profit for the year, profit attributable to owners, comprehensive income, basic EPS, finance income and costs
- **Balance sheet** — total assets, current and non-current assets, property plant and equipment, total liabilities, current and non-current liabilities, equity, issued capital, cash
- **Cash flow** — operating, investing and financing
- **Every one of those with the prior year beside it**, so growth is a subtraction rather than a second run
- **What the company says about itself**, where it tagged it: registered office, domicile, country of incorporation, legal form, principal activities
- **Quality flags** — the filing's own XBRL validation error and warning counts, and a link to the report in a viewer with every tagged figure highlighted

Measured across 36 filings from 12 countries on 2026-08-28:

| Column | Populated | With prior year |
|---|---|---|
| Profit / loss | **100%** | 100% |
| Equity | **100%** | 97% |
| Cash and cash equivalents | **100%** | 100% |
| Cash flow (all three) | **100%** | 100% |
| Total assets | 97% | 94% |
| Revenue | 94% | 94% |
| Operating profit | 91% | 91% |

### The thing that makes the difference

The repository assigns each filing a reporting date, and **that date is wrong for about 30% of filings**. It is inferred from dates tagged anywhere in the report, so a debt maturity or a subsequent-event date can win.

Measured on 2026-08-28: Carrefour is indexed as `2026-12-31` against figures ending 2025-12-31. Castellum as `2029-05-01` against figures ending 2022-12-31. Recordati as `2032-12-31`.

Read that date and take the figures matching it, and roughly a third of your rows come back **completely empty while looking perfectly well-formed**. This Actor ignores it and derives the reporting period from the facts themselves — the date carrying the most consolidated figures. That is the single change that took revenue coverage from 63% to 94%, and equity from 69% to 100%.

Both dates are exported: `periodEnd` is the one the figures support, `indexedPeriodEnd` is the repository's, and `periodEndDisagrees` flags the rows where they differ.

### Which figures are the real ones

An annual report tags the same line many times — once as a consolidated total, then again per segment, per geography, per product. This Actor reads **only the consolidated totals**, never a breakdown.

It also reconciles the ways filers name the same line. `ifrs-full:Revenue` covers 70% of filings; adding `RevenueFromContractsWithCustomers` and `RevenueAndOperatingIncome` takes it to about 94%. The `revenueConcept` column names which one answered, so a fallback is never mistaken for a direct tag.

### Example output

One real record, exported on 2026-08-28. Null columns removed for readability; note that the balance sheet reconciles — assets 1,939,000 = liabilities 1,697,000 + equity 242,000:

```json
{
  "lei": "81560069517A53E0F607",
  "entityName": "EEMS ITALIA SPA",
  "country": "IT",
  "periodEnd": "2024-12-31",
  "indexedPeriodEnd": "2024-12-31",
  "periodEndDisagrees": false,
  "filingSystem": "ESEF",
  "currency": "EUR",
  "validationErrors": 0,
  "validationWarnings": 1,
  "addedToIndex": "2025-11-18",
  "revenue": 649000.0,
  "revenueConcept": "Revenue",
  "revenuePriorYear": 1234000.0,
  "operatingProfit": -3513000.0,
  "operatingProfitPriorYear": -3003000.0,
  "profitBeforeTax": -3558000.0,
  "profitBeforeTaxPriorYear": -3018000.0,
  "incomeTaxExpense": 0.0,
  "profitLoss": -3558000.0,
  "profitLossPriorYear": -3018000.0,
  "profitAttributableToOwners": -3558000.0,
  "profitAttributableToOwnersPriorYear": -3018000.0,
  "comprehensiveIncome": -3579000.0,
  "comprehensiveIncomePriorYear": -3051000.0,
  "financeIncome": 0.0,
  "financeIncomePriorYear": 38000.0,
  "financeCosts": 44000.0,
  "financeCostsPriorYear": 53000.0,
  "assets": 1939000.0,
  "assetsPriorYear": 3950000.0,
  "currentAssets": 1162000.0,
  "currentAssetsPriorYear": 2833000.0,
  "noncurrentAssets": 777000.0,
  "noncurrentAssetsPriorYear": 1117000.0,
  "propertyPlantAndEquipment": 7000.0,
  "propertyPlantAndEquipmentPriorYear": 105000.0,
  "liabilities": 1697000.0,
  "liabilitiesPriorYear": 1524000.0,
  "currentLiabilities": 1539000.0,
  "currentLiabilitiesPriorYear": 1391000.0,
  "noncurrentLiabilities": 158000.0,
  "noncurrentLiabilitiesPriorYear": 133000.0,
  "equity": 242000.0,
  "equityPriorYear": 2426000.0,
  "cashAndCashEquivalents": 271000.0,
  "cashAndCashEquivalentsPriorYear": 1493000.0,
  "cashFlowOperating": -3144000.0,
  "cashFlowOperatingPriorYear": -2297000.0,
  "cashFlowInvesting": 4000.0,
  "cashFlowInvestingPriorYear": -304000.0,
  "cashFlowFinancing": 1918000.0,
  "cashFlowFinancingPriorYear": 2500000.0,
  "reportedEntityName": "EEMS Italia S.p.A.",
  "registeredOffice": "Via Antonio da Recanate, 2, Milano",
  "domicile": "Italia",
  "countryOfIncorporation": "Italia",
  "legalForm": "Società per Azioni",
  "principalActivities": "Grossista Gas ed energia elettrica",
  "factCount": 284,
  "reportUrl": "https://filings.xbrl.org/81560069517A53E0F607/2024-12-31/ESEF/IT/0/81560069517A53E0F607-2024-12-31-0-it/reports/81560069517A53E0F607-2024-12-31-0-it.xhtml",
  "viewerUrl": "https://filings.xbrl.org/81560069517A53E0F607/2024-12-31/ESEF/IT/0/81560069517A53E0F607-2024-12-31-0-it/reports/ixbrlviewer.html",
  "sourceApi": "filings.xbrl.org/api",
  "source": "filings.xbrl.org (XBRL International) — ESEF / UKSEF / Ukraine filings"
}
```

### Input

| Field | What it does |
|---|---|
| `countries` | Two-letter codes of the filing authority: IT, FR, NL, ES, FI, DK, SE, PL, BE, NO, GB, AT, UA and more. Empty means every country. |
| `periodEndFrom` / `periodEndTo` | Reporting-period window, `YYYY-MM-DD`. |
| `lei` | A single Legal Entity Identifier, to pull every year one company has filed. |
| `skipFilingsWithErrors` | Drop filings whose own XBRL fails validation. Off by default — the `validationErrors` column lets you decide per row. |
| `maxItems` | Stop after this many statements. Each one is a separate download, so large runs take time. |
| `includeRaw` | Attach the complete xBRL-JSON: every note and breakdown, hundreds of facts per company. |

### Coverage, stated plainly

The repository holds **25,675 filings**. Sampled counts on 2026-08-28: GB 2,897, FR 1,178, FI 1,168, IT 872, and smaller volumes for DK, PL, NL, ES, BE, NO, SE, AT, HU, IS, HR and UA. Periods run from 2020 to 2026.

**Germany and Ireland are not in the index.** XBRL International states their filings cannot be reliably discovered or downloaded. No tool built on this source can return them, and this Actor says so in the run log rather than returning an empty result.

The date filters run on the repository's own date, so a filing whose date is wrong can fall outside a window you would expect it in. `periodEndDisagrees` is there to make that visible.

### Pricing

Pay per result: charged once per statement actually exported. A filing whose data cannot be read is never exported and never charged — the repository deliberately keeps filings whose conversion failed, and those carry no figures.

### Where the data comes from

`filings.xbrl.org` is operated by XBRL International and collects filings from each country's Officially Appointed Mechanism. Its terms, quoted from the repository's own about page on 2026-08-28: *"At present, there are no restrictions on the ways that the data can be used."* The API is free, and XBRL International reserves the right to rate-limit or withdraw it; this Actor paces its requests accordingly.

The filings themselves are public regulatory documents. No personal data is involved.

### Frequently asked questions

**How is this different from the SEC XBRL Actors?**
Those read US EDGAR filings. This reads European ESEF and UKSEF filings, plus Ukraine. Different companies, different regulator, same idea.

**Why is a column empty for some companies?**
Because that company did not tag that line as a consolidated total. IFRS lets filers choose their level of detail, and smaller filers tag less. The coverage table above is measured, not promised.

**Can I get every year for one company?**
Yes — put its LEI in the `lei` field and leave the dates empty.

**Are these consolidated or parent-only figures?**
Whatever the company filed as its primary statements. Groups file consolidated accounts, so for most filers these are group figures.

**Do I get the notes to the accounts?**
Not as columns. Turn on `includeRaw` and every tagged fact in the report comes with the row, notes included.

**Does it work as an MCP tool?**
Yes. Like every Apify Actor it exposes an MCP endpoint, so an AI agent can ask the European Company Financials Actor for a company's numbers directly.

### Related Actors

- **GLEIF LEI Scraper** — resolve any LEI in these rows to its full legal entity record
- **Finland Company Register** and **Norway Company Register Search** — national registers for the companies behind the filings
- **France Company Register Scraper** — France, with named directors

# Actor input Schema

## `countries` (type: `array`):

Two-letter codes of the filing authority: IT, FR, NL, ES, FI, DK, SE, PL, BE, NO, GB, AT, UA and more. Leave empty for every country. Germany and Ireland are NOT in the index - their filings cannot be reliably discovered.

## `periodEndFrom` (type: `string`):

Only statements whose reporting period ends on or after this date (YYYY-MM-DD). Leave empty for no lower bound.

## `periodEndTo` (type: `string`):

Only statements whose reporting period ends on or before this date (YYYY-MM-DD). Leave empty for no upper bound.

## `lei` (type: `string`):

A single Legal Entity Identifier, to pull every year one company has filed. Example: 815600FBF92FD3531704

## `skipFilingsWithErrors` (type: `boolean`):

The repository keeps filings whose own XBRL breaks the specification. Turn this on to export only clean ones; leave it off and read the validationErrors column instead.

## `maxItems` (type: `integer`):

Stop after this many exported statements. 0 means no limit. Each statement is a separate download, so large runs take time.

## `includeRaw` (type: `boolean`):

Attach the complete xBRL-JSON for the filing - hundreds of facts per company, including every note and breakdown.

## Actor input object example

```json
{
  "skipFilingsWithErrors": false,
  "maxItems": 50,
  "includeRaw": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per filed financial statement, with income statement, balance sheet and cash flow in named IFRS columns. Every exported row is one dataset item.

# 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 = {
    "periodEndFrom": "",
    "periodEndTo": "",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("publicdata/esef-european-company-financials").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 = {
    "periodEndFrom": "",
    "periodEndTo": "",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("publicdata/esef-european-company-financials").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 '{
  "periodEndFrom": "",
  "periodEndTo": "",
  "maxItems": 50
}' |
apify call publicdata/esef-european-company-financials --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,publicdata/esef-european-company-financials"
        }
    }
}

```

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/vq0fN5nPZBCEXc9Ag/builds/gnYkqyrzwdYWaLndW/openapi.json
