Tidy R interface to Norway’s Central Coordinating Register for Legal Entities (Enhetsregisteret), maintained by the Brønnøysund Register Centre. The register contains approximately 1 million active entities. Data is published under the Norwegian Licence for Open Government Data (NLOD 2.0).
This repository holds three packages that are versioned and built together:
| Package | Directory | Purpose |
|---|---|---|
| tidybrreg | / |
The typed client: sixteen functions, one per register endpoint. CRAN-bound. |
| tidybrregpanel | tidybrregpanel/ |
Managed state: Parquet snapshots, brreg_sync(), replay, changelog, flows, panels, series, networks, survival data. |
| tidybrregmcp | tidybrregmcp/ |
A Model Context Protocol server whose tools, schemas and documentation are derived from tidybrreg’s exports and help pages. |
| tidybrreg-mcp | tidybrreg-mcp-node/ |
The same server without R: an npm package (npx tidybrreg-mcp) built from the manifest tidybrregmcp writes, for Claude, ChatGPT and OpenAI clients. |
install.packages(c("tidybrreg", "tidybrregpanel", "tidybrregmcp"),
repos = c("https://sondreskarsten.r-universe.dev",
"https://cloud.r-project.org"))
# Or from GitHub
pak::pak("sondreskarsten/tidybrreg")
pak::pak("sondreskarsten/tidybrreg/tidybrregpanel")
pak::pak("sondreskarsten/tidybrreg/tidybrregmcp")
library(tidybrreg)
brreg_entity("923609016")
#> # A tibble: 1 x 63
#> org_nr name legal_form founding_date employees nace_1
#> <chr> <chr> <chr> <date> <int> <chr>
#> 1 923609016 EQUINOR ASA ASA 1972-09-18 21408 06.100
# Sub-entities (establishments)
brreg_entity("974760843", registry = "underenheter")
Only observed fields are emitted; registry and deleted are always
present. Codes by default. Translate with type = "label" or
brreg_label():
brreg_entity("923609016", type = "label")
brreg_entity("923609016") |>
brreg_label(code = c("legal_form", "nace_1"))
brreg_label(c("AS", "ENK"), dic = "legal_form", lang = "no")
brreg_search(legal_form = "AS", municipality_code = "0301",
min_employees = 500, max_results = 10)
# Sub-entity search
brreg_search(name = "Equinor", registry = "underenheter", max_results = 5)
A query that matches more than the register’s 10,000-result window
aborts with tidybrreg_error_result_window rather than returning a
partial population; results carry total_matches and complete
attributes.
brreg_roles("923609016") # who holds roles IN an entity
brreg_roles_legal("923609016") # roles an entity holds in OTHER entities
brreg_konsern("923609016") # the corporate group tree
brreg_signatur("923609016") # who may sign for the entity
brreg_prokura("923609016") # procuration holders
acc <- brreg_regnskap("923609016") # one row per filing, up to 3 years per type
acc[c("account_type", "period_end", "currency", "consistent")]
tidyr::unnest(acc, items) # statement, group, item, path, level, is_sum, value
brreg_regnskap("923609016", account_type = "SELSKAP", year = 2025)
The figures are nested per filing and keep the API's structure, so a group's total and its components are never summed together by accident; consistent and inconsistencies flag filings whose accounting identities do not hold (the register publishes them as filed). Banks, insurers and pension funds answer with a plan the API does not serve; the result is the typed empty with unsupported_plan and a tidybrreg_warning_unsupported_plan.
brreg_updates(since = "2026-03-01T00:00:00Z", size = 1000, max_pages = 10)
brreg_update_fields(since = Sys.Date() - 1)
brreg_updates(type = "roller", since = Sys.Date() - 1)
entities <- brreg_download(type = "enheter") # ~196 MB JSON
sub_entities <- brreg_download(type = "underenheter") # ~75 MB JSON
roles <- brreg_download(type = "roller") # ~131 MB JSON
path <- brreg_download(type_output = "path")
library(tidybrreg)
brreg_validate(c("923609016", "984851006", "123456789"))
#> [1] TRUE TRUE FALSE
Codes by default, labels on demand. Functions return Norwegian
codes. brreg_label() translates to English or Norwegian via bundled
reference data or live SSB KLASS lookups;
options(tidybrreg.offline = TRUE) stays on the bundled dictionaries.
Observed fields only. A column is present when the register emitted
the field; nothing is fabricated as NA. Unknown API fields pass
through with auto-generated snake_case names (zero-drop policy).
Typed conditions. Every error and warning has a class and fields
(?tidybrreg_conditions): deleted entities, partial or truncated
results, result-window overflow, unknown feed members,
bundled-dictionary fallback.
One coercion rule. Dictionary types are identical on the live JSON path and the bulk JSON path; parse failures are reported, never fatal.
UTC instants. Feed timestamps and HTTP dates are UTC POSIXct
whatever the session time zone.
| Function | Description |
|---|---|
brreg_entity() |
Single entity by organization number (enheter or underenheter) |
brreg_search() |
Filtered search (enheter or underenheter) |
brreg_underenheter() |
Sub-units of an entity |
brreg_children() |
Children in the ORGL administrative hierarchy |
brreg_roles() |
Board members, officers, auditors for an entity |
brreg_roles_legal() |
Reverse: roles an entity holds in other entities |
brreg_konsern() |
Corporate group structure |
brreg_signatur() |
Signature authority |
brreg_prokura() |
Procuration |
brreg_regnskap() |
Annual accounts from Regnskapsregisteret, nested per filing with consistency flags |
brreg_updates() |
Incremental change stream (enheter, underenheter, roller) |
brreg_update_fields() |
Flat field-level changes |
brreg_download() |
Full register bulk download (enheter, underenheter, roller) |
brreg_label() |
Translate codes to descriptions |
get_brreg_dic() |
Fetch/cache NACE or sector dictionaries |
brreg_validate() |
Organization number validation (modulus-11) |
tidybrregmcp serves these sixteen functions to any Model Context
Protocol client. Tool names are the function names and the descriptions
are the help pages, so the server changes exactly when this package
changes.
{"mcpServers": {"tidybrreg": {"command": "Rscript", "args": ["-e", "tidybrregmcp::mcp_serve()"]}}}
Without R, from npm:
{"mcpServers": {"tidybrreg": {"command": "npx", "args": ["-y", "tidybrreg-mcp"]}}}
See tidybrregmcp/README.md and tidybrreg-mcp-node/README.md.
MIT. Data from Enhetsregisteret is available under NLOD
2.0 and must be attributed to the
Brønnøysund Register Centre; see ?tidybrreg_provenance for the sources
of the bundled tables.