tidybrreg provides tidy access to Norway’s Central Coordinating Register for Legal Entities (Enhetsregisteret), maintained by the Brønnøysund Register Centre at data.brreg.no. The register contains approximately 1 million active entities — companies, partnerships, sole proprietorships, associations, and government bodies.
The package is a thin, typed client: fifteen functions that each wrap one register endpoint and return a tibble with English column names. Persistence, synchronisation and panel construction live in the companion package tidybrregpanel.
Installation
# From r-universe (pre-built binaries)
install.packages("tidybrreg",
repos = c("https://sondreskarsten.r-universe.dev",
"https://cloud.r-project.org"))
# Or from GitHub
pak::pak("sondreskarsten/tidybrreg")Look up a single entity
Every Norwegian legal entity has a unique 9-digit organization number (organisasjonsnummer). Look up Equinor ASA:
library(tidybrreg)
brreg_entity("923609016")
#> # A tibble: 1 × 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.100The result is a tibble with English column names mapped from the
Norwegian API via the package’s field_dict. Only the fields
the register emitted for that entity are present: a sole proprietorship
carries no employees or founding_date, a
foreign branch no municipality_code. Test for a column with
%in% names() rather than assuming it. Two columns are
always present: registry (which registry answered) and
deleted.
A deleted entity is returned, not hidden. Both of the register’s
signals (HTTP 410, and HTTP 200 with
respons_klasse = "SlettetEnhet") yield
deleted = TRUE, a parsed deletion_date, the
remaining observed fields, and a
tidybrreg_warning_deleted.
Translate codes to labels
By default, functions return raw codes (ASA,
06.100). Two ways to get labels:
# Option 1: inline via type = "label"
brreg_entity("923609016", type = "label")
# Option 2: pipe to brreg_label() for more control
brreg_entity("923609016") |>
brreg_label(code = c("legal_form", "nace_1"))
#> legal_form = "Public limited company"
#> legal_form_code = "ASA" (original code preserved)
#> nace_1 = "Extraction of crude petroleum"
#> nace_1_code = "06.100"
# Norwegian labels
brreg_label(c("AS", "ENK"), dic = "legal_form", lang = "no")The code = argument keeps the original code in a
_code suffixed column alongside the label — following the
eurostat package’s pattern. Legal-form and role labels are bundled; NACE
and sector labels come from the SSB KLASS API on first use and are
cached for the session. Set
options(tidybrreg.offline = TRUE) to stay on the bundled
English dictionaries; see ?get_brreg_dic.
Search for entities
Query by name, legal form, geography, industry, employee count, or any combination:
# Large private companies in Oslo
brreg_search(
legal_form = "AS",
municipality_code = "0301",
min_employees = 500,
max_results = 10
)Search results are paginated automatically up to
max_results. The register’s search window is 10,000
results: when a query matches more than that and you ask for more than
the window, the call aborts with a
tidybrreg_error_result_window instead of returning a
partial population. When fewer rows are returned than matched, the
result carries attr(x, "complete") == FALSE and
attr(x, "total_matches") and a
tidybrreg_warning_truncated is signalled. For larger
extractions, use brreg_download().
Sub-entities (establishments)
Use registry = "underenheter" to search sub-entities —
branch offices, plants, and establishments linked to a parent
entity:
brreg_search(name = "Equinor", registry = "underenheter", max_results = 5)
brreg_underenheter("923609016")Retrieve roles, groups and signing authority
Board members, officers, and auditors for any entity:
roles <- brreg_roles("923609016")
roles
#> # A tibble: 25 × 17
#> org_nr role_group role first_name last_name birth_date
#> <chr> <chr> <chr> <chr> <chr> <date>
#> 1 923609016 Board of Directors Chair of the Board Jon Erik Reinhardsen 1960-07-14
#> 2 923609016 Board of Directors Board member ...
# Roles Equinor holds in other entities
brreg_roles_legal("923609016")
# The corporate group tree
brreg_konsern("923609016")
# Who may sign for the entity, and procuration holders
brreg_signatur("923609016")
brreg_prokura("923609016")These per-entity endpoints share one status contract (see
?brreg_roles): HTTP 404 returns the typed zero-row tibble
with attribute http_status = 404L and no warning (the
ordinary case for a company that is in no group), HTTP 410 warns about
deletion, and any other failure is a
tidybrreg_error_http.
Follow changes
The change data capture feeds report what changed since an instant:
brreg_updates(since = "2026-03-01T00:00:00Z", size = 1000, max_pages = 10)
brreg_update_fields(since = Sys.Date() - 1, size = 500)
brreg_updates(type = "roller", since = Sys.Date() - 1)since is sent as a UTC instant and timestamps come back
as UTC POSIXct. The result carries complete,
pages_fetched and cursor attributes; pass
cursor + 1 to resume.
Bulk download the full register
Three registries available:
# Main entities: ~196 MB JSON
entities <- brreg_download(type = "enheter")
# Sub-entities: ~75 MB JSON
sub_entities <- brreg_download(type = "underenheter")
# All roles for all entities: ~131 MB JSON
all_roles <- brreg_download(type = "roller")
# Only the file
path <- brreg_download(type_output = "path")Downloads are cached in
tools::R_user_dir("tidybrreg", "cache"). Use
refresh = TRUE to force re-download, or
refresh = "auto" to re-download only when the server’s
validators (ETag, Last-Modified) differ from the cached copy’s.
Conditions
Every error and warning the package raises has a class you can catch
or silence selectively; see ?tidybrreg_conditions.
tryCatch(
brreg_search(municipality_code = "4601", max_results = 20000),
tidybrreg_error_result_window = function(e) e$total_matches
)
suppressWarnings(brreg_konsern("923609016"), classes = "tidybrreg_warning_deleted")Function → API endpoint mapping
| Function | API endpoint | Returns |
|---|---|---|
brreg_entity(org_nr) |
/enheter/{orgnr} |
1-row tibble |
brreg_entity(org_nr, registry = "underenheter") |
/underenheter/{orgnr} |
1-row tibble |
brreg_search(...) |
/enheter?... |
N-row tibble |
brreg_search(..., registry = "underenheter") |
/underenheter?... |
N-row tibble |
brreg_underenheter(org_nr),
brreg_children(org_nr)
|
/underenheter?overordnetEnhet=,
/enheter?overordnetEnhet=
|
N-row tibble |
brreg_roles(org_nr) |
/enheter/{orgnr}/roller |
N-row tibble |
brreg_roles_legal(org_nr) |
/roller/enheter/{orgnr}/juridiskeroller |
N-row tibble |
brreg_konsern(org_nr) |
/konsernstruktur/{orgnr} |
N-row tibble |
brreg_signatur(org_nr),
brreg_prokura(org_nr)
|
fullmakt/enheter/{orgnr}/signatur,
.../prokura
|
N-row tibble |
brreg_download("enheter") |
/enheter/lastned |
Full register tibble |
brreg_download("underenheter") |
/underenheter/lastned |
Full sub-entity tibble |
brreg_download("roller") |
/roller/totalbestand |
Full roles tibble |
brreg_updates(type = "enheter"),
brreg_update_fields()
|
/oppdateringer/enheter |
Change events tibble |
brreg_updates(type = "roller") |
/oppdateringer/roller |
Change events tibble |
get_brreg_dic("nace") |
SSB KLASS classifications/6/codesAt
|
Dictionary tibble |
Next steps
-
vignette("business-data")— Norwegian legal forms, NACE codes, and data quirks - The tidybrregpanel package — snapshots, synchronisation, panels, flows, networks
- The tidybrregmcp package — the same fifteen functions as Model Context Protocol tools