# Denmark Annual Reports by CVR: Financials (Årsrapport) (`nordicdata/dk-annual-accounts`) Actor

Danish company financial statements from annual reports filed with Erhvervsstyrelsen (CVR): revenue, gross profit, profit, equity, total assets, cash and employees. Search by CVR number or filing date. One JSON row per annual report (regnskab), no API key needed.

- **URL**: https://apify.com/nordicdata/dk-annual-accounts.md
- **Developed by:** [Mikkel Jeppesen Juhl](https://apify.com/nordicdata) (community)
- **Categories:** Business, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 annual report with figures

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Denmark Annual Reports by CVR: Financials (Årsrapport)

Get Danish company financials from annual reports (årsrapport, regnskab) as clean JSON. One row per annual report, straight from the official filings of Erhvervsstyrelsen (the Danish Business Authority), found by CVR number or publication date. No API key needed.

Give it CVR numbers, a publication date window, or both. The actor finds the annual reports, reads the XBRL documents and returns revenue, gross profit, operating profit, profit before tax, profit for the year, staff costs, average employees, equity, total assets and cash, with the period, currency and reporting class.

### Use cases

- Look up revenue, profit, equity and total assets for a list of Danish companies by CVR number.
- Screen Danish companies by financial figures for credit checks, due diligence or lead lists.
- Pull every annual report published in a date window into a database.
- Feed parsed Danish financial statements to analysis tools or AI agents.

For the filing history and PDF links of a single company, use the CVR number as input and read `xhtmlUrl` and `pdfUrl`.

### What you get

| Field | Meaning |
| --- | --- |
| `cvr` | Danish company number, 8 digits |
| `companyName` | Name in the report |
| `periodStart`, `periodEnd` | Financial year |
| `publishedAt` | When Erhvervsstyrelsen published the filing |
| `reportType` | "Årsrapport" or "Annual report" |
| `reportingClass` | Regnskabsklasse: `B`, `B micro`, `C medium`, `C large`, `D` |
| `currency` | ISO code from the XBRL unit (DKK, EUR, USD and so on) |
| `revenue` | Nettoomsætning / Revenue |
| `grossProfit` | Bruttofortjeneste / Gross profit |
| `operatingProfit` | Resultat af primær drift / Operating profit |
| `profitBeforeTax` | Resultat før skat |
| `profitLoss` | Årets resultat / Profit for the year |
| `staffCosts` | Personaleomkostninger |
| `averageEmployees` | Gennemsnitligt antal ansatte |
| `equity` | Egenkapital, end of year |
| `totalAssets` | Aktiver i alt / Balance, end of year |
| `cash` | Likvide beholdninger, end of year |
| `isCorrection` | True when the filing corrects an earlier one (omgørelse) |
| `filingId` | Erhvervsstyrelsen id of the filing |
| `parseError` | Why a row has no figures, else null |
| `xbrlUrl`, `xhtmlUrl`, `pdfUrl` | Source documents (when `includeDocumentUrls` is on) |

Figures are in whole currency units, not thousands. A figure is null when the report does not contain it. Small companies (class B) may report gross profit and leave out revenue, and most do.

The actor reads only current year figures: duration facts must match the report period, balance sheet facts must sit on the last day of the period, and facts with dimensions (for example equity per reserve) are skipped. Prior year comparatives are never mixed in.

Listed and large companies (class C large and D) file their figures in a separate IFRS (ESEF) document. The actor reads it automatically when the Danish GAAP document has no figures.

The output has no person names. The actor skips the chair of the general meeting, auditors, board members and the management.

### Input

```json
{
  "cvrNumbers": ["10224640"],
  "publishedFrom": "2026-10-01",
  "publishedTo": "2026-10-21",
  "maxResults": 100,
  "includeDocumentUrls": true,
  "skipFilingsWithoutXbrl": true,
  "requestIntervalSeconds": 0.5
}
```

Leave `cvrNumbers` empty to get every annual report in the date window. Newest filings come first. Half-year reports and other filing types are skipped.

### Coverage

Measured on 2026-10-21 on the 200 newest annual reports (199 with XBRL) and on 20 reports from 10 large companies. Details: `raw/2026-10-21-dk-annual-accounts-test-run.md` in the company repository.

| Field | 199 recent reports | 20 large company reports |
| --- | --- | --- |
| companyName, period, publishedAt, currency | 100% | 100% |
| reportingClass | 100% | 95% |
| revenue | 7% | 95% |
| grossProfit | 96% | 60% |
| operatingProfit | 85% | 80% |
| profitBeforeTax | 98% | 100% |
| profitLoss | 100% | 100% |
| staffCosts | 47% | 30% |
| averageEmployees | 95% | 5% |
| equity | 100% | 100% |
| totalAssets | 100% | 100% |
| cash | 93% | 100% |

Spot checks against the human readable reports matched every figure in 8 of 8 reports checked.

### Run it locally

No Apify account is needed. You need `uv`.

```bash
cd apps/apify-dk-annual-accounts
uv sync
./run_local.sh input.example.json
ls storage/datasets/default/
uv run python test/coverage.py storage/datasets/default
uv run python test/spotcheck.py storage/datasets/default 5
```

`run_local.sh` copies the input to `storage/key_value_stores/default/INPUT.json` and runs `python -m src`. The Apify SDK sees no token and uses local storage. Run stats land in `storage/key_value_stores/default/RUN_STATS`.

Docker: `docker build -f .actor/Dockerfile -t dk-annual-accounts .` and mount a storage folder at `/usr/src/app/storage` with `-e CRAWLEE_STORAGE_DIR=/usr/src/app/storage`.

### Source and terms

Data comes from the free system-to-system access to annual report data from Erhvervsstyrelsen (`distribution.virk.dk/offentliggoerelser`) and the documents on `regnskaber.virk.dk`. Erhvervsstyrelsen's "Vilkår for brug af danske offentlige data" allow commercial and non-commercial use. Contains data used under the terms for use of Danish public data ("Indeholder data, som benyttes i henhold til vilkår for brug af danske offentlige data"). Erhvervsstyrelsen does not endorse this actor. The legally valid report is the one filed with Erhvervsstyrelsen. Check `xhtmlUrl` before you rely on a figure.

### Pricing

Pay per event: 0.01 USD per annual report row with figures. Rows with a `parseError` are free. No start fee.

# Actor input Schema

## `cvrNumbers` (type: `array`):

Danish company numbers (8 digits). Leave empty to read every company in the date window.

## `publishedFrom` (type: `string`):

Earliest publication date, YYYY-MM-DD.

## `publishedTo` (type: `string`):

Latest publication date, YYYY-MM-DD.

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

Stop after this many rows. Newest filings come first.

## `includeDocumentUrls` (type: `boolean`):

Add links to the XBRL, XHTML and PDF documents.

## `skipFilingsWithoutXbrl` (type: `boolean`):

Older and some foreign filings only have a PDF. When off, they appear as rows with null figures and are not charged.

## `requestIntervalSeconds` (type: `number`):

Pause between requests to the public servers.

## Actor input object example

```json
{
  "cvrNumbers": [
    "10224640"
  ],
  "maxResults": 100,
  "includeDocumentUrls": true,
  "skipFilingsWithoutXbrl": true,
  "requestIntervalSeconds": 0.5
}
```

# Actor output Schema

## `results` (type: `string`):

One row per annual report with key figures from the XBRL filing.

## `runStats` (type: `string`):

Summary counts for the run, such as how many rows were written.

# 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 = {
    "cvrNumbers": [
        "10224640"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nordicdata/dk-annual-accounts").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 = { "cvrNumbers": ["10224640"] }

# Run the Actor and wait for it to finish
run = client.actor("nordicdata/dk-annual-accounts").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 '{
  "cvrNumbers": [
    "10224640"
  ]
}' |
apify call nordicdata/dk-annual-accounts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nordicdata/dk-annual-accounts"
        }
    }
}
```

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/nXhJt5vicDfgEvOBG/builds/7DUmwI4H5VXGpqoJV/openapi.json
