# Brønnøysund Company Lookup: Norway Business Registry API (`accountable_eel/brreg-company-lookup`) Actor

Look up Norwegian companies by organization number against Brønnøysund Register Centre's official, free registry. Get legal form, NACE industry code, address, employee count, VAT status, and bankruptcy flags. Pay only for numbers that resolve.

- **URL**: https://apify.com/accountable\_eel/brreg-company-lookup.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 successful lookups

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

## Brønnøysund Company Lookup

You give this actor a list of Norwegian organization numbers. It looks each one up against the
[Brønnøysund Register Centre](https://data.brreg.no)'s official, free Enhetsregisteret (Central
Coordinating Register for Legal Entities) API and returns one flat row per number — legal name,
legal form, NACE industry code, registered address, employee count, VAT registration, and
bankruptcy/liquidation status. No API key, no scraping: this calls the Norwegian government's own
registry endpoint directly, for every input, every run.

### Who it's for

The accountable\_eel catalogue sells company intelligence columns for outbound. Each actor takes a
list of domains or company identifiers and returns one flat, stably-named row per input —
firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an
n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and
per-domain: a few tenths of a cent for a row that was actually found, and nothing for a
miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists —
VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No
seat licence, no monthly minimum, no credit system to decode. For Norway specifically, that
official source is Brønnøysund's Enhetsregisteret — the same register a Norwegian bank or notary
would check.

### Why this one

- **Official registry, not a scrape.** `src/target.js` hits
  `data.brreg.no/enhetsregisteret/api/enheter/<orgnr>` directly — the same JSON the Brønnøysund
  website itself is built on.
- **Compliance flags in the same row as firmographics.** Bankruptcy and under-liquidation status
  come back alongside legal form, industry code, and employee count — you don't make a second call
  to ask "is this company still solvent."
- **9-digit organization numbers only, and it says so.** No name-matching, no fuzzy search — this
  is a deterministic lookup, so a wrong or malformed number fails cleanly as `BAD_FORMAT` instead
  of guessing.
- **Misses are still rows, and rows are still free.** A number that doesn't resolve comes back with
  `"found": false"` and a plain-English reason, but is never billed.
- **Built for a list, not a lookup.** Concurrency, keyword filtering, and column selection are all
  configurable inputs — feed in a few numbers or a few thousand.

#### Use cases

- **KYB / vendor onboarding.** Confirm a Norwegian counterparty is registered, solvent, and not
  under liquidation before you sign a contract or set up a payment relationship with them.
- **Sales and lead enrichment.** Attach legal form, industry code, and employee count to a list of
  Norwegian prospect organization numbers you already have from a CRM export or a scrape.
- **Credit and risk screening.** Batch-check bankruptcy and under-liquidation flags across a
  portfolio of Norwegian entities on a schedule, instead of checking them one at a time on the
  Brønnøysund website.
- **Compliance data refresh.** Re-verify VAT registration status and registered address for
  entities already sitting in your CRM, so stale records get caught before an audit does.

### What you get

Every input produces exactly one row. These fields are always present:

| Field | Type | Description |
|---|---|---|
| `query` | text | The organization number you submitted, unmodified |
| `found` | boolean | `true` if a matching entity was found (and billed), `false` if not |
| `status` | text | `OK`, `NOT_FOUND`, or `BAD_FORMAT` |
| `message` | text | Plain-English reason for a miss (omitted when `found` is `true`) |
| `scrapedAt` | ISO 8601 timestamp | When this row was fetched |

When `found` is `true`, these fields are also populated:

| Field | Type | Description |
|---|---|---|
| `organizationNumber` | text | The 9-digit Brønnøysund organization number, normalized |
| `name` | text | Registered legal name |
| `organizationFormCode` | text | Legal form code, e.g. `AS`, `ASA`, `ENK` |
| `organizationFormDescription` | text | Legal form spelled out, e.g. "Aksjeselskap" |
| `industryCode` | text | Primary NACE industry code |
| `industryDescription` | text | Industry description matching that code |
| `registrationDate` | date | Date the entity was registered in Enhetsregisteret |
| `employeeCount` | number | Employee count on file (can be `null` if not reported) |
| `vatRegistered` | boolean | Whether the entity is registered in the VAT (MVA) register |
| `bankrupt` | boolean | Bankruptcy flag |
| `underLiquidation` | boolean | Under-liquidation flag |
| `address` | object | `{ street, postalCode, city, municipality }` — registered business address, falling back to postal address when no business address is on file |
| `website` | text | Company website, when Brønnøysund has one on file (often `null`) |

Field names are stable across runs — this is what lets an AI agent or a Clay HTTP column read the
schema once and keep working.

### Price

$4 per 1,000 organization numbers, plus a $0.00005 start fee. Misses (`found:false`) are never charged.

That works out to $0.004 per found row on the FREE tier, dropping to $0.002 per found row on
Apify's GOLD tier — the actor-start fee is flat regardless of tier. 1,000 organization numbers
through this actor: **~$4** if every one is found, less if some aren't. The same 1,000 rows through
a credit-based enrichment platform: **$80–$400**. A miss — a number that isn't registered, or one
you typed wrong — still comes back as a dataset row with `found: false`, but you're never billed
for it.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `organizationNumbers` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"organizationNumbers":["923609016","984851006"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

1) Paste one 9-digit organization number per line into `organizationNumbers`, or pass an array of
   them via the API.
2) Turn on `testRun` for your first attempt — it caps the run at the first 5 numbers so you can
   check the shape of the output before spending on the full list.
3) Run the actor. One row comes back per number, in the same order you submitted them.
4) If you only want rows that resolved, turn on `onlyFound` — misses are dropped from the dataset
   entirely (and were never billed regardless).
5) Use `columns` to narrow the output to just the fields you need, and `includeKeywords` /
   `excludeKeywords` to filter rows by content (e.g. exclude anything with `underLiquidation` in
   the text, or keep only a specific industry code).

### Input

```json
{
  "organizationNumbers": [
    "923609016",
    "984851006"
  ]
}
```

One 9-digit Brønnøysund organization number per line. Accepted formats: 923609016, spaces and dashes are removed automatically.

```json
{
  "organizationNumbers": ["923609016", "984851006"],
  "testRun": false,
  "onlyFound": false,
  "maxConcurrency": 5
}
```

`organizationNumbers` is a list of 9-digit Norwegian organization numbers — spaces and
dashes are removed automatically. One dataset row is returned per number; rows with
`"found": false` are never charged. Turn on `testRun` to try your list against just the
first 5 numbers before running the full batch. Optional `includeKeywords` /
`excludeKeywords` filter rows by content, `maxResults` caps the run early, and `columns`
lets you pick which fields to return.

### Sample output

| query | found | status | organizationNumber | name | organizationFormCode | organizationFormDescription | industryCode | industryDescription | registrationDate | employeeCount | vatRegistered | bankrupt | underLiquidation | address | website | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 923609016 | true | OK | 923609016 | EQUINOR ASA | ASA | Allmennaksjeselskap | 06.100 | Utvinning av råolje | 1995-03-12 | 21239 | true | false | false | {"street":"Forusbeen 50","postalCode":"4035","city":"STAVANGER","municipality":"STAVANGER"} | www.equinor.com | 2026-08-31T06:10:16.580Z |

One row per organization number, for example:

```json
{
  "query": "923609016",
  "found": true,
  "status": "OK",
  "organizationNumber": "923609016",
  "name": "EQUINOR ASA",
  "organizationFormCode": "ASA",
  "organizationFormDescription": "Allmennaksjeselskap",
  "industryCode": "06.100",
  "industryDescription": "Utvinning av råolje",
  "registrationDate": "1995-03-15",
  "employeeCount": 21500,
  "vatRegistered": true,
  "bankrupt": false,
  "underLiquidation": false,
  "address": {
    "street": "Forusbeen 50",
    "postalCode": "4035",
    "city": "STAVANGER",
    "municipality": "STAVANGER"
  },
  "website": "www.equinor.com",
  "scrapedAt": "2026-08-21T10:00:00.000Z"
}
```

Numbers that don't resolve still get a row (`"found": false`, `"status": "NOT_FOUND"` or
`"BAD_FORMAT"`, with a plain-English `message`), so you always get one row per input —
but you're never charged for those.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"organizationNumbers":["923609016","984851006"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"organizationNumbers":["923609016","984851006"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"organizationNumbers":["{{organization number}}"]}`, mapping the row's organization number into the `organizationNumbers` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Norway Company Registry Lookup | Apify" — the agent will find and run this actor.

### Tips

- Run `testRun: true` on a new list first — it's free-ish (5 numbers) and confirms your input
  format before you commit a large batch.
- Turn on `onlyFound` when you're feeding results straight into a CRM or Clay table and don't want
  `NOT_FOUND` rows cluttering the import.
- `bankrupt` and `underLiquidation` are separate flags — a company can be `underLiquidation: true`
  and `bankrupt: false` (voluntary winding-up is not the same as insolvency).
- `employeeCount` and `website` are both frequently `null` — not every entity reports employees to
  Brønnøysund, and many small entities have no website on file. Don't treat a `null` as an error.
- If you already have organization numbers from another source (a CRM field, a scrape, an earlier
  actor run), strip anything that isn't 9 digits before you submit — `BAD_FORMAT` rows are free but
  they're still a row you have to filter out downstream.
- `industryCode` follows Norway's NACE classification, not NAICS or SIC — if you're filtering or
  joining against a US-sourced dataset, map the code rather than string-matching the description.
- The `address` object falls back from business address to postal address automatically, but a
  small number of entities (shell companies, some foundations) file neither — expect an occasional
  `null` there even on an otherwise fully populated row.

### vs. alternatives

| | What it costs | What you get | Trade-off |
|---|---|---|---|
| **This actor** (`brreg-company-lookup`) | $0.004 per found row (FREE tier, less on paid tiers), $0.00005 actor start, nothing for a miss | One row per organization number — legal form, NACE industry code, registered address, employee count, VAT status, bankruptcy/liquidation flags | Norwegian organization numbers only, exact match — no company-name search, and it won't resolve a number that's typed wrong or belongs to a different country |
| **Brønnøysund directly** | Free | The same data, from the same source | It's the same source — this actor exists for the batch: thousands of numbers in, thousands of rows out, retries and rate limits handled, in the format your table already reads. One number, once? Use the portal. |
| **Clay** | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable *from* Clay via its HTTP step. |
| **Doing it yourself** | Your time + handling Brønnøysund's response shapes (address falls back between two different fields, 404s serve no Content-Type header) and rate limits across a list | The same data | This actor absorbs the edge cases already found in `src/target.js` — the missing-header 404, the address fallback — so you don't rediscover them one failed request at a time |

Prices for third-party tools are their published list prices as of August 2026 and are not
tracked here — check the vendor before relying on the comparison.

### FAQ

**What happens when an organization number isn't found?**
You get a row with `"found": false`, `"status": "NOT_FOUND"`, and a plain-English `message`. It
counts toward your dataset but not toward your bill — only rows with `found: true` are charged.

**What if I submit something that isn't a valid organization number?**
It's rejected before any request is made, returned as `"status": "BAD_FORMAT"`, and not charged.
Spaces and dashes are stripped automatically (`923 609 016` and `923-609-016` both normalize to
`923609016`), but anything that isn't 9 digits after that fails as `BAD_FORMAT`.

**Are there rate limits?**
`maxConcurrency` controls how many requests run in parallel (default 5) — set it lower if you want
to be gentler on Brønnøysund's API, or raise it for a large batch. The actor doesn't impose its own
cap beyond that; Brønnøysund's public API doesn't publish a documented rate limit, but very high
concurrency on a very large list is the thing most likely to trigger throttling on their end. If
you're running thousands of numbers and see failed requests climb, dropping `maxConcurrency` to 2
or 3 usually clears it up.

**How fresh is the data?**
Each row reflects what Enhetsregisteret returned at the moment the actor ran (`scrapedAt` records
that timestamp). Nothing is cached or stored between runs — if a company's status changes in
Brønnøysund's register, whether that's a new bankruptcy filing, an address change, or a VAT
deregistration, the next run picks it up. There's no lag between what the actor returns and what
the register currently shows.

**Does this need proxies?**
No. Brønnøysund's API is public, unauthenticated, and not behind bot protection — the actor calls
it directly.

**Is this personal data, and does GDPR apply?**
The fields returned are entity-level — legal name, registered address, industry code, employee
count, compliance flags — not data about named individuals. This actor doesn't return board
members, signatories, or any other named-person fields, so there's no personal-data question to
navigate on that front. It's public Norwegian company-register data either way, not scraped from a
third-party site — the same records a Norwegian bank, landlord, or notary would pull to check a
counterparty before signing anything with them.

**What's the difference between `organizationFormCode` values I might see?**
The most common are `AS` (private limited company), `ASA` (public limited company, like the
Equinor example above), `ENK` (sole proprietorship), and `STI` (foundation) — but Enhetsregisteret
covers dozens of legal forms, including associations and public-sector entities. `organizationFormDescription` spells out whichever code comes back, so you don't need to memorize the
list.

**Can I schedule this to re-run on a list I already have?**
Yes — set it up as an Apify scheduled task with a saved input, and each run re-checks your list
against the live register. There's no delta or "changed since last run" mode built in; every run
re-fetches every number.

**Can an AI agent call this directly?**
Yes, via the Apify MCP server — an agent asks for "Norway Company Registry Lookup | Apify" and can
run it with a list of organization numbers, no separate integration code needed.

**Does this cover anything outside Norway?**
No. It only resolves entities registered in Norway's Enhetsregisteret. For Finnish entities, see
`prh-company-lookup`; for a single call that checks several national registries at once, see
`company-registry-unified-lookup`.

### Related actors

- [PRH Company Lookup](https://apify.com/accountable_eel/prh-company-lookup)
- [Company Registry Unified Lookup](https://apify.com/accountable_eel/company-registry-unified-lookup)
- [EU VAT Validator](https://apify.com/accountable_eel/eu-vat-validator)

# Actor input Schema

## `organizationNumbers` (type: `array`):

One 9-digit Brønnøysund organization number per line. Accepted formats: 923609016, spaces and dashes are removed automatically. You're only charged for the ones we actually find — a miss costs nothing.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

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

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## `proxyConfiguration` (type: `object`):

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "organizationNumbers": [
    "923609016",
    "984851006"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "columns": [
    "organizationNumber",
    "name",
    "organizationFormCode",
    "organizationFormDescription",
    "industryCode",
    "industryDescription",
    "registrationDate",
    "employeeCount",
    "vatRegistered",
    "bankrupt",
    "underLiquidation",
    "address",
    "website"
  ],
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "organizationNumbers": [
        "923609016",
        "984851006"
    ],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/brreg-company-lookup").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 = {
    "organizationNumbers": [
        "923609016",
        "984851006",
    ],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/brreg-company-lookup").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 '{
  "organizationNumbers": [
    "923609016",
    "984851006"
  ],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call accountable_eel/brreg-company-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/brreg-company-lookup"
        }
    }
}
```

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/Invw0zfTvUzL2HjIH/builds/fDLTUzw06s1pj0j4k/openapi.json
